diff options
author | PJ Fanning <fanningpj@apache.org> | 2021-05-22 21:37:08 +0000 |
---|---|---|
committer | PJ Fanning <fanningpj@apache.org> | 2021-05-22 21:37:08 +0000 |
commit | 33f6381c434dfe09201d0ff5d2b5716e1b836a1d (patch) | |
tree | a7f4d93a64088650c055a58c47f91fcf119b3b71 /poi-scratchpad | |
parent | db53f9b860310294b6c83d53479431945e8ad489 (diff) | |
download | poi-33f6381c434dfe09201d0ff5d2b5716e1b836a1d.tar.gz poi-33f6381c434dfe09201d0ff5d2b5716e1b836a1d.zip |
convert tabs to spaces
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1890122 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'poi-scratchpad')
212 files changed, 14341 insertions, 14341 deletions
diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/HDGFDiagram.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/HDGFDiagram.java index 4f578c58f7..5a916618e3 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/HDGFDiagram.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/HDGFDiagram.java @@ -42,113 +42,113 @@ import org.apache.poi.util.LocaleUtil; * http://www.gnome.ru/projects/docs/slide2.png */ public final class HDGFDiagram extends POIReadOnlyDocument { - private static final String VISIO_HEADER = "Visio (TM) Drawing\r\n"; - - private long docSize; - - private Pointer trailerPointer; - private TrailerStream trailer; - - public HDGFDiagram(POIFSFileSystem fs) throws IOException { - this(fs.getRoot()); - } - - public HDGFDiagram(DirectoryNode dir) throws IOException { - super(dir); - - // Grab the document stream - final byte[] _docstream; - try (InputStream is = dir.createDocumentInputStream("VisioDocument")) { - _docstream = IOUtils.toByteArray(is); - } - - // Check it's really visio - String typeString = new String(_docstream, 0, 20, LocaleUtil.CHARSET_1252 ); - if(! typeString.equals(VISIO_HEADER)) { - throw new IllegalArgumentException("Wasn't a valid visio document, started with " + typeString); - } - - // Grab the version number, 0x1a -> 0x1b - short version = LittleEndian.getShort(_docstream, 0x1a); - // Grab the document size, 0x1c -> 0x1f - docSize = LittleEndian.getUInt(_docstream, 0x1c); - // ??? 0x20 -> 0x23 - - // Create the Chunk+Pointer Factories for the document version - PointerFactory ptrFactory = new PointerFactory(version); - ChunkFactory chunkFactory = new ChunkFactory(version); - - // Grab the pointer to the trailer - trailerPointer = ptrFactory.createPointer(_docstream, 0x24); - - // Now grab the trailer - trailer = (TrailerStream) - Stream.createStream(trailerPointer, _docstream, chunkFactory, ptrFactory); - - // Finally, find all our streams - trailer.findChildren(_docstream); - } - - /** - * Returns the TrailerStream, which is at the root of the - * tree of Streams. - * - * @return the TrailerStream - */ - public TrailerStream getTrailerStream() { return trailer; } - - /** - * Returns all the top level streams, which are the streams - * pointed to by the TrailerStream. - * - * @return the top level streams - */ - public Stream[] getTopLevelStreams() { return trailer.getPointedToStreams(); } - - public long getDocumentSize() { return docSize; } - - /** - * Prints out some simple debug on the base contents of the file. - * @see org.apache.poi.hdgf.dev.VSDDumper - */ - public void debug() { - System.err.println("Trailer is at " + trailerPointer.getOffset()); - System.err.println("Trailer has type " + trailerPointer.getType()); - System.err.println("Trailer has length " + trailerPointer.getLength()); - System.err.println("Trailer has format " + trailerPointer.getFormat()); - - for(int i=0; i<trailer.getPointedToStreams().length; i++) { - Stream stream = trailer.getPointedToStreams()[i]; - Pointer ptr = stream.getPointer(); - - System.err.println("Looking at pointer " + i); - System.err.println("\tType is " + ptr.getType() + "\t\t" + Integer.toHexString(ptr.getType())); - System.err.println("\tOffset is " + ptr.getOffset() + "\t\t" + Long.toHexString(ptr.getOffset())); - System.err.println("\tAddress is " + ptr.getAddress() + "\t" + Long.toHexString(ptr.getAddress())); - System.err.println("\tLength is " + ptr.getLength() + "\t\t" + Long.toHexString(ptr.getLength())); - System.err.println("\tFormat is " + ptr.getFormat() + "\t\t" + Long.toHexString(ptr.getFormat())); - System.err.println("\tCompressed is " + ptr.destinationCompressed()); - System.err.println("\tStream is " + stream.getClass()); - - if(stream instanceof PointerContainingStream) { - PointerContainingStream pcs = (PointerContainingStream)stream; - - if(pcs.getPointedToStreams() != null && pcs.getPointedToStreams().length > 0) { - System.err.println("\tContains " + pcs.getPointedToStreams().length + " other pointers/streams"); - for(int j=0; j<pcs.getPointedToStreams().length; j++) { - Stream ss = pcs.getPointedToStreams()[j]; - Pointer sptr = ss.getPointer(); - System.err.println("\t\t" + j + " - Type is " + sptr.getType() + "\t\t" + Integer.toHexString(sptr.getType())); - System.err.println("\t\t" + j + " - Length is " + sptr.getLength() + "\t\t" + Long.toHexString(sptr.getLength())); - } - } - } - - if(stream instanceof StringsStream) { - System.err.println("\t\t**strings**"); - StringsStream ss = (StringsStream)stream; - System.err.println("\t\t" + ss._getContentsLength()); - } - } - } + private static final String VISIO_HEADER = "Visio (TM) Drawing\r\n"; + + private long docSize; + + private Pointer trailerPointer; + private TrailerStream trailer; + + public HDGFDiagram(POIFSFileSystem fs) throws IOException { + this(fs.getRoot()); + } + + public HDGFDiagram(DirectoryNode dir) throws IOException { + super(dir); + + // Grab the document stream + final byte[] _docstream; + try (InputStream is = dir.createDocumentInputStream("VisioDocument")) { + _docstream = IOUtils.toByteArray(is); + } + + // Check it's really visio + String typeString = new String(_docstream, 0, 20, LocaleUtil.CHARSET_1252 ); + if(! typeString.equals(VISIO_HEADER)) { + throw new IllegalArgumentException("Wasn't a valid visio document, started with " + typeString); + } + + // Grab the version number, 0x1a -> 0x1b + short version = LittleEndian.getShort(_docstream, 0x1a); + // Grab the document size, 0x1c -> 0x1f + docSize = LittleEndian.getUInt(_docstream, 0x1c); + // ??? 0x20 -> 0x23 + + // Create the Chunk+Pointer Factories for the document version + PointerFactory ptrFactory = new PointerFactory(version); + ChunkFactory chunkFactory = new ChunkFactory(version); + + // Grab the pointer to the trailer + trailerPointer = ptrFactory.createPointer(_docstream, 0x24); + + // Now grab the trailer + trailer = (TrailerStream) + Stream.createStream(trailerPointer, _docstream, chunkFactory, ptrFactory); + + // Finally, find all our streams + trailer.findChildren(_docstream); + } + + /** + * Returns the TrailerStream, which is at the root of the + * tree of Streams. + * + * @return the TrailerStream + */ + public TrailerStream getTrailerStream() { return trailer; } + + /** + * Returns all the top level streams, which are the streams + * pointed to by the TrailerStream. + * + * @return the top level streams + */ + public Stream[] getTopLevelStreams() { return trailer.getPointedToStreams(); } + + public long getDocumentSize() { return docSize; } + + /** + * Prints out some simple debug on the base contents of the file. + * @see org.apache.poi.hdgf.dev.VSDDumper + */ + public void debug() { + System.err.println("Trailer is at " + trailerPointer.getOffset()); + System.err.println("Trailer has type " + trailerPointer.getType()); + System.err.println("Trailer has length " + trailerPointer.getLength()); + System.err.println("Trailer has format " + trailerPointer.getFormat()); + + for(int i=0; i<trailer.getPointedToStreams().length; i++) { + Stream stream = trailer.getPointedToStreams()[i]; + Pointer ptr = stream.getPointer(); + + System.err.println("Looking at pointer " + i); + System.err.println("\tType is " + ptr.getType() + "\t\t" + Integer.toHexString(ptr.getType())); + System.err.println("\tOffset is " + ptr.getOffset() + "\t\t" + Long.toHexString(ptr.getOffset())); + System.err.println("\tAddress is " + ptr.getAddress() + "\t" + Long.toHexString(ptr.getAddress())); + System.err.println("\tLength is " + ptr.getLength() + "\t\t" + Long.toHexString(ptr.getLength())); + System.err.println("\tFormat is " + ptr.getFormat() + "\t\t" + Long.toHexString(ptr.getFormat())); + System.err.println("\tCompressed is " + ptr.destinationCompressed()); + System.err.println("\tStream is " + stream.getClass()); + + if(stream instanceof PointerContainingStream) { + PointerContainingStream pcs = (PointerContainingStream)stream; + + if(pcs.getPointedToStreams() != null && pcs.getPointedToStreams().length > 0) { + System.err.println("\tContains " + pcs.getPointedToStreams().length + " other pointers/streams"); + for(int j=0; j<pcs.getPointedToStreams().length; j++) { + Stream ss = pcs.getPointedToStreams()[j]; + Pointer sptr = ss.getPointer(); + System.err.println("\t\t" + j + " - Type is " + sptr.getType() + "\t\t" + Integer.toHexString(sptr.getType())); + System.err.println("\t\t" + j + " - Length is " + sptr.getLength() + "\t\t" + Long.toHexString(sptr.getLength())); + } + } + } + + if(stream instanceof StringsStream) { + System.err.println("\t\t**strings**"); + StringsStream ss = (StringsStream)stream; + System.err.println("\t\t" + ss._getContentsLength()); + } + } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/Chunk.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/Chunk.java index 6ccc5a6797..19eda1e7f7 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/Chunk.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/Chunk.java @@ -286,11 +286,11 @@ public final class Chunk { * process CommandDefinitions, and so doesn't actually exist * in the chunk */ -// public static class VirtualCommand extends Command { -// private VirtualCommand(CommandDefinition definition) { -// super(definition); -// } -// } +// public static class VirtualCommand extends Command { +// private VirtualCommand(CommandDefinition definition) { +// super(definition); +// } +// } /** * A special kind of command that holds the offset to * a block diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkFactory.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkFactory.java index 76b5937338..ff7c56eac3 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkFactory.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkFactory.java @@ -42,182 +42,182 @@ import static org.apache.logging.log4j.util.Unbox.box; */ public final class ChunkFactory { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; - /** The version of the currently open document */ - private int version; - /** - * Key is a Chunk's type, value is an array of its CommandDefinitions - */ - private final Map<Integer, CommandDefinition[]> chunkCommandDefinitions = + /** The version of the currently open document */ + private int version; + /** + * Key is a Chunk's type, value is an array of its CommandDefinitions + */ + private final Map<Integer, CommandDefinition[]> chunkCommandDefinitions = new HashMap<>(); - /** - * What the name is of the chunk table definitions file? - * This file comes from the scratchpad resources directory. - */ - private static final String chunkTableName = - "/org/apache/poi/hdgf/chunks_parse_cmds.tbl"; - - /** For logging problems we spot with the file */ - private static final Logger LOG = LogManager.getLogger(ChunkFactory.class); - - public ChunkFactory(int version) throws IOException { - this.version = version; - - processChunkParseCommands(); - } - - /** - * Open chunks_parse_cmds.tbl and process it, to get the definitions - * of all the different possible chunk commands. - */ - private void processChunkParseCommands() throws IOException { - try (InputStream cpd = ChunkFactory.class.getResourceAsStream(chunkTableName)) { - if(cpd == null) { - throw new IllegalStateException("Unable to find HDGF chunk definition on the classpath - " + chunkTableName); - } - - try (BufferedReader inp = new BufferedReader(new InputStreamReader(cpd, LocaleUtil.CHARSET_1252))) { - String line; - while ((line = inp.readLine()) != null) { - if (line.isEmpty() || "# \t".contains(line.substring(0, 1))) { - continue; - } - - // Start xxx - if (!line.matches("^start [0-9]+$")) { - throw new IllegalStateException("Expecting start xxx, found " + line); - } - int chunkType = Integer.parseInt(line.substring(6)); - ArrayList<CommandDefinition> defsL = new ArrayList<>(); - - // Data entries - while ((line = inp.readLine()) != null) { - if (line.startsWith("end")) { - break; - } - StringTokenizer st = new StringTokenizer(line, " "); - int defType = Integer.parseInt(st.nextToken()); - int offset = Integer.parseInt(st.nextToken()); - String name = st.nextToken("\uffff").substring(1); - - CommandDefinition def = new CommandDefinition(defType, offset, name); - defsL.add(def); - } - - CommandDefinition[] defs = defsL.toArray(new CommandDefinition[0]); - - // Add to the map - chunkCommandDefinitions.put(chunkType, defs); - } - } - } - } - - public int getVersion() { return version; } - - /** - * Creates the appropriate chunk at the given location. - * - * @param data the chunk bytes - * @param offset the offset into the chunk bytes array to start reading from - * - * @return the new Chunk - */ - public Chunk createChunk(byte[] data, int offset) { - // Create the header - ChunkHeader header = - ChunkHeader.createChunkHeader(version, data, offset); - // Sanity check - if(header.getLength() < 0) { - throw new IllegalArgumentException("Found a chunk with a negative length, which isn't allowed"); - } - - // How far up to look - int endOfDataPos = offset + header.getLength() + header.getSizeInBytes(); - - // Check we have enough data, and tweak the header size - // as required - if(endOfDataPos > data.length) { - LOG.atWarn().log("Header called for {} bytes, but that would take us past the end of the data!", box(header.getLength())); - - endOfDataPos = data.length; - header.setLength(data.length - offset - header.getSizeInBytes()); - - if(header.hasTrailer()) { - header.setLength(header.getLength() - 8); - endOfDataPos -= 8; - } - if(header.hasSeparator()) { + /** + * What the name is of the chunk table definitions file? + * This file comes from the scratchpad resources directory. + */ + private static final String chunkTableName = + "/org/apache/poi/hdgf/chunks_parse_cmds.tbl"; + + /** For logging problems we spot with the file */ + private static final Logger LOG = LogManager.getLogger(ChunkFactory.class); + + public ChunkFactory(int version) throws IOException { + this.version = version; + + processChunkParseCommands(); + } + + /** + * Open chunks_parse_cmds.tbl and process it, to get the definitions + * of all the different possible chunk commands. + */ + private void processChunkParseCommands() throws IOException { + try (InputStream cpd = ChunkFactory.class.getResourceAsStream(chunkTableName)) { + if(cpd == null) { + throw new IllegalStateException("Unable to find HDGF chunk definition on the classpath - " + chunkTableName); + } + + try (BufferedReader inp = new BufferedReader(new InputStreamReader(cpd, LocaleUtil.CHARSET_1252))) { + String line; + while ((line = inp.readLine()) != null) { + if (line.isEmpty() || "# \t".contains(line.substring(0, 1))) { + continue; + } + + // Start xxx + if (!line.matches("^start [0-9]+$")) { + throw new IllegalStateException("Expecting start xxx, found " + line); + } + int chunkType = Integer.parseInt(line.substring(6)); + ArrayList<CommandDefinition> defsL = new ArrayList<>(); + + // Data entries + while ((line = inp.readLine()) != null) { + if (line.startsWith("end")) { + break; + } + StringTokenizer st = new StringTokenizer(line, " "); + int defType = Integer.parseInt(st.nextToken()); + int offset = Integer.parseInt(st.nextToken()); + String name = st.nextToken("\uffff").substring(1); + + CommandDefinition def = new CommandDefinition(defType, offset, name); + defsL.add(def); + } + + CommandDefinition[] defs = defsL.toArray(new CommandDefinition[0]); + + // Add to the map + chunkCommandDefinitions.put(chunkType, defs); + } + } + } + } + + public int getVersion() { return version; } + + /** + * Creates the appropriate chunk at the given location. + * + * @param data the chunk bytes + * @param offset the offset into the chunk bytes array to start reading from + * + * @return the new Chunk + */ + public Chunk createChunk(byte[] data, int offset) { + // Create the header + ChunkHeader header = + ChunkHeader.createChunkHeader(version, data, offset); + // Sanity check + if(header.getLength() < 0) { + throw new IllegalArgumentException("Found a chunk with a negative length, which isn't allowed"); + } + + // How far up to look + int endOfDataPos = offset + header.getLength() + header.getSizeInBytes(); + + // Check we have enough data, and tweak the header size + // as required + if(endOfDataPos > data.length) { + LOG.atWarn().log("Header called for {} bytes, but that would take us past the end of the data!", box(header.getLength())); + + endOfDataPos = data.length; + header.setLength(data.length - offset - header.getSizeInBytes()); + + if(header.hasTrailer()) { + header.setLength(header.getLength() - 8); + endOfDataPos -= 8; + } + if(header.hasSeparator()) { header.setLength(header.getLength() - 4); - endOfDataPos -= 4; - } - } - - - // Create the trailer and separator, if required - ChunkTrailer trailer = null; - ChunkSeparator separator = null; - if(header.hasTrailer()) { - if(endOfDataPos <= data.length-8) { - trailer = new ChunkTrailer( - data, endOfDataPos); - endOfDataPos += 8; - } else { - LOG.atError().log("Header claims a length to {} there's then no space for the trailer in the data ({})", box(endOfDataPos),box(data.length)); - } - } - if(header.hasSeparator()) { - if(endOfDataPos <= data.length-4) { - separator = new ChunkSeparator( - data, endOfDataPos); - } else { - LOG.atError().log("Header claims a length to {} there's then no space for the separator in the data ({})", box(endOfDataPos),box(data.length)); - } - } - - // Now, create the chunk - byte[] contents = IOUtils.safelyClone(data, offset+header.getSizeInBytes(), header.getLength(), MAX_RECORD_LENGTH); - Chunk chunk = new Chunk(header, trailer, separator, contents); - - // Feed in the stuff from chunks_parse_cmds.tbl - CommandDefinition[] defs = chunkCommandDefinitions.get(header.getType()); - if (defs == null) { - defs = new CommandDefinition[0]; - } - chunk.setCommandDefinitions(defs); - - // Now get the chunk to process its commands - chunk.processCommands(); - - // All done - return chunk; - } - - /** - * The definition of a Command, which a chunk may hold. - * The Command holds the value, this describes it. - */ - public static class CommandDefinition { - private int type; - private int offset; - private String name; - public CommandDefinition(int type, int offset, String name) { - this.type = type; - this.offset = offset; - this.name = name; - } - - public String getName() { - return name; - } - public int getOffset() { - return offset; - } - public int getType() { - return type; - } - } + endOfDataPos -= 4; + } + } + + + // Create the trailer and separator, if required + ChunkTrailer trailer = null; + ChunkSeparator separator = null; + if(header.hasTrailer()) { + if(endOfDataPos <= data.length-8) { + trailer = new ChunkTrailer( + data, endOfDataPos); + endOfDataPos += 8; + } else { + LOG.atError().log("Header claims a length to {} there's then no space for the trailer in the data ({})", box(endOfDataPos),box(data.length)); + } + } + if(header.hasSeparator()) { + if(endOfDataPos <= data.length-4) { + separator = new ChunkSeparator( + data, endOfDataPos); + } else { + LOG.atError().log("Header claims a length to {} there's then no space for the separator in the data ({})", box(endOfDataPos),box(data.length)); + } + } + + // Now, create the chunk + byte[] contents = IOUtils.safelyClone(data, offset+header.getSizeInBytes(), header.getLength(), MAX_RECORD_LENGTH); + Chunk chunk = new Chunk(header, trailer, separator, contents); + + // Feed in the stuff from chunks_parse_cmds.tbl + CommandDefinition[] defs = chunkCommandDefinitions.get(header.getType()); + if (defs == null) { + defs = new CommandDefinition[0]; + } + chunk.setCommandDefinitions(defs); + + // Now get the chunk to process its commands + chunk.processCommands(); + + // All done + return chunk; + } + + /** + * The definition of a Command, which a chunk may hold. + * The Command holds the value, this describes it. + */ + public static class CommandDefinition { + private int type; + private int offset; + private String name; + public CommandDefinition(int type, int offset, String name) { + this.type = type; + this.offset = offset; + this.name = name; + } + + public String getName() { + return name; + } + public int getOffset() { + return offset; + } + public int getType() { + return type; + } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeader.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeader.java index f5493ac643..7eec5d36bb 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeader.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeader.java @@ -25,98 +25,98 @@ import org.apache.poi.util.LittleEndian; * A chunk header */ public abstract class ChunkHeader { - private int type; - private int id; - private int length; - private int unknown1; - - /** - * Creates the appropriate ChunkHeader for the Chunk Header at - * the given location, for the given document version. - * - * @param documentVersion the documentVersion - 4 and higher is supported - * @param data the chunk data - * @param offset the start offset in the chunk data - * @return the ChunkHeader - */ - public static ChunkHeader createChunkHeader(int documentVersion, byte[] data, int offset) { - if(documentVersion >= 6) { - ChunkHeaderV6 ch; - if(documentVersion > 6) { - ch = new ChunkHeaderV11(); - } else { - ch = new ChunkHeaderV6(); - } - ch.setType((int)LittleEndian.getUInt(data, offset + 0)); - ch.setId((int)LittleEndian.getUInt(data, offset + 4)); - ch.setUnknown1((int)LittleEndian.getUInt(data, offset + 8)); - ch.setLength((int)LittleEndian.getUInt(data, offset + 12)); - ch.setUnknown2(LittleEndian.getShort(data, offset + 16)); - ch.setUnknown3(LittleEndian.getUByte(data, offset + 18)); - - return ch; - } else if(documentVersion == 5 || documentVersion == 4) { - ChunkHeaderV4V5 ch = new ChunkHeaderV4V5(); - - ch.setType(LittleEndian.getShort(data, offset + 0)); - ch.setId(LittleEndian.getShort(data, offset + 2)); - ch.setUnknown2(LittleEndian.getUByte(data, offset + 4)); - ch.setUnknown3(LittleEndian.getUByte(data, offset + 5)); - ch.setUnknown1(LittleEndian.getShort(data, offset + 6)); - ch.setLength(Math.toIntExact(LittleEndian.getUInt(data, offset + 8))); - - return ch; - } else { - throw new IllegalArgumentException("Visio files with versions below 4 are not supported, yours was " + documentVersion); - } - } - - /** - * Returns the size of a chunk header for the given document version. - * - * @param documentVersion the documentVersion - 4 and higher is supported - * - * @return the header size - */ - public static int getHeaderSize(int documentVersion) { - return documentVersion >= 6 ? ChunkHeaderV6.getHeaderSize() : ChunkHeaderV4V5.getHeaderSize(); - } - - public abstract int getSizeInBytes(); - public abstract boolean hasTrailer(); - public abstract boolean hasSeparator(); - public abstract Charset getChunkCharset(); - - /** - * @return the ID/IX of the chunk - */ - public int getId() { - return id; - } - - /** - * Returns the length of the trunk, excluding the length - * of the header, trailer or separator. - * - * @return the length of the trunk - */ - public int getLength() { - return length; - } - - /** - * Returns the type of the chunk, which affects the - * mandatory information - * - * @return the type of the chunk - */ - public int getType() { - return type; - } - - public int getUnknown1() { - return unknown1; - } + private int type; + private int id; + private int length; + private int unknown1; + + /** + * Creates the appropriate ChunkHeader for the Chunk Header at + * the given location, for the given document version. + * + * @param documentVersion the documentVersion - 4 and higher is supported + * @param data the chunk data + * @param offset the start offset in the chunk data + * @return the ChunkHeader + */ + public static ChunkHeader createChunkHeader(int documentVersion, byte[] data, int offset) { + if(documentVersion >= 6) { + ChunkHeaderV6 ch; + if(documentVersion > 6) { + ch = new ChunkHeaderV11(); + } else { + ch = new ChunkHeaderV6(); + } + ch.setType((int)LittleEndian.getUInt(data, offset + 0)); + ch.setId((int)LittleEndian.getUInt(data, offset + 4)); + ch.setUnknown1((int)LittleEndian.getUInt(data, offset + 8)); + ch.setLength((int)LittleEndian.getUInt(data, offset + 12)); + ch.setUnknown2(LittleEndian.getShort(data, offset + 16)); + ch.setUnknown3(LittleEndian.getUByte(data, offset + 18)); + + return ch; + } else if(documentVersion == 5 || documentVersion == 4) { + ChunkHeaderV4V5 ch = new ChunkHeaderV4V5(); + + ch.setType(LittleEndian.getShort(data, offset + 0)); + ch.setId(LittleEndian.getShort(data, offset + 2)); + ch.setUnknown2(LittleEndian.getUByte(data, offset + 4)); + ch.setUnknown3(LittleEndian.getUByte(data, offset + 5)); + ch.setUnknown1(LittleEndian.getShort(data, offset + 6)); + ch.setLength(Math.toIntExact(LittleEndian.getUInt(data, offset + 8))); + + return ch; + } else { + throw new IllegalArgumentException("Visio files with versions below 4 are not supported, yours was " + documentVersion); + } + } + + /** + * Returns the size of a chunk header for the given document version. + * + * @param documentVersion the documentVersion - 4 and higher is supported + * + * @return the header size + */ + public static int getHeaderSize(int documentVersion) { + return documentVersion >= 6 ? ChunkHeaderV6.getHeaderSize() : ChunkHeaderV4V5.getHeaderSize(); + } + + public abstract int getSizeInBytes(); + public abstract boolean hasTrailer(); + public abstract boolean hasSeparator(); + public abstract Charset getChunkCharset(); + + /** + * @return the ID/IX of the chunk + */ + public int getId() { + return id; + } + + /** + * Returns the length of the trunk, excluding the length + * of the header, trailer or separator. + * + * @return the length of the trunk + */ + public int getLength() { + return length; + } + + /** + * Returns the type of the chunk, which affects the + * mandatory information + * + * @return the type of the chunk + */ + public int getType() { + return type; + } + + public int getUnknown1() { + return unknown1; + } void setType(int type) { this.type = type; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeaderV4V5.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeaderV4V5.java index b4eb9d83d7..97be9616e8 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeaderV4V5.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeaderV4V5.java @@ -23,46 +23,46 @@ import java.nio.charset.Charset; * A chunk header from v4 or v5 */ public final class ChunkHeaderV4V5 extends ChunkHeader { - private short unknown2; - private short unknown3; + private short unknown2; + private short unknown3; - public short getUnknown2() { - return unknown2; - } - public short getUnknown3() { - return unknown3; - } + public short getUnknown2() { + return unknown2; + } + public short getUnknown3() { + return unknown3; + } - protected static int getHeaderSize() { - return 12; - } + protected static int getHeaderSize() { + return 12; + } - public int getSizeInBytes() { - return getHeaderSize(); - } + public int getSizeInBytes() { + return getHeaderSize(); + } - /** - * Does the chunk have a trailer? - */ - public boolean hasTrailer() { - // V4 and V5 never has trailers - return false; - } + /** + * Does the chunk have a trailer? + */ + public boolean hasTrailer() { + // V4 and V5 never has trailers + return false; + } - /** - * Does the chunk have a separator? - */ - public boolean hasSeparator() { - // V4 and V5 never has separators - return false; - } + /** + * Does the chunk have a separator? + */ + public boolean hasSeparator() { + // V4 and V5 never has separators + return false; + } - @Override - public Charset getChunkCharset() { - return Charset.forName("ASCII"); - } + @Override + public Charset getChunkCharset() { + return Charset.forName("ASCII"); + } - void setUnknown2(short unknown2) { + void setUnknown2(short unknown2) { this.unknown2 = unknown2; } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeaderV6.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeaderV6.java index 2a221a7028..81bbe1ba14 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeaderV6.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkHeaderV6.java @@ -23,49 +23,49 @@ import java.nio.charset.Charset; * A chunk header from v6 */ public class ChunkHeaderV6 extends ChunkHeader { - private short unknown2; - private short unknown3; + private short unknown2; + private short unknown3; - public short getUnknown2() { - return unknown2; - } - public short getUnknown3() { - return unknown3; - } + public short getUnknown2() { + return unknown2; + } + public short getUnknown3() { + return unknown3; + } - protected static int getHeaderSize() { - // Looks like it ought to be 19... - return 19; - } - public int getSizeInBytes() { - return getHeaderSize(); - } + protected static int getHeaderSize() { + // Looks like it ought to be 19... + return 19; + } + public int getSizeInBytes() { + return getHeaderSize(); + } - /** - * Does the chunk have a trailer? - */ - public boolean hasTrailer() { - switch (getType()) { - case 0x2c: case 0x65: case 0x66: case 0x69: - case 0x6a: case 0x6b: case 0x70: case 0x71: - return true; + /** + * Does the chunk have a trailer? + */ + public boolean hasTrailer() { + switch (getType()) { + case 0x2c: case 0x65: case 0x66: case 0x69: + case 0x6a: case 0x6b: case 0x70: case 0x71: + return true; default: return (getUnknown1() != 0); - } - } + } + } - /** - * Does the chunk have a separator? - */ - public boolean hasSeparator() { - // V6 never has separators - return false; - } + /** + * Does the chunk have a separator? + */ + public boolean hasSeparator() { + // V6 never has separators + return false; + } - @Override - public Charset getChunkCharset() { - return Charset.forName("ASCII"); - } + @Override + public Charset getChunkCharset() { + return Charset.forName("ASCII"); + } void setUnknown2(short unknown2) { this.unknown2 = unknown2; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkSeparator.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkSeparator.java index ee009db15e..35dcaba93d 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkSeparator.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkSeparator.java @@ -24,13 +24,13 @@ import java.util.Arrays; * header of the next one */ public final class ChunkSeparator { - final byte[] separatorData; + final byte[] separatorData; - public ChunkSeparator(byte[] data, int offset) { - separatorData = Arrays.copyOfRange(data, offset, offset+4); - } + public ChunkSeparator(byte[] data, int offset) { + separatorData = Arrays.copyOfRange(data, offset, offset+4); + } - public String toString() { - return "<ChunkSeparator of length " + separatorData.length + ">"; - } + public String toString() { + return "<ChunkSeparator of length " + separatorData.length + ">"; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkTrailer.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkTrailer.java index 92160abb8e..9b0973ec5a 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkTrailer.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/ChunkTrailer.java @@ -23,15 +23,15 @@ import java.util.Arrays; * A trailer that follows a chunk */ public final class ChunkTrailer { - private final byte[] trailerData; + private final byte[] trailerData; - public ChunkTrailer(byte[] data, int offset) { - trailerData = Arrays.copyOfRange(data, offset, offset+8); - } + public ChunkTrailer(byte[] data, int offset) { + trailerData = Arrays.copyOfRange(data, offset, offset+8); + } - public String toString() { - return "<ChunkTrailer of length " + trailerData.length + ">"; - } + public String toString() { + return "<ChunkTrailer of length " + trailerData.length + ">"; + } byte[] getTrailerData() { return trailerData; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/dev/VSDDumper.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/dev/VSDDumper.java index a82e914edd..ddbd4801d9 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/dev/VSDDumper.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/dev/VSDDumper.java @@ -44,63 +44,63 @@ public final class VSDDumper { this.hdgf = hdgf; } - public static void main(String[] args) throws Exception { - if(args.length == 0) { - System.err.println("Use:"); - System.err.println(" VSDDumper <filename>"); - System.exit(1); - } - - try (POIFSFileSystem poifs = new POIFSFileSystem(new File(args[0])); - HDGFDiagram hdgf = new HDGFDiagram(poifs)) { + public static void main(String[] args) throws Exception { + if(args.length == 0) { + System.err.println("Use:"); + System.err.println(" VSDDumper <filename>"); + System.exit(1); + } + + try (POIFSFileSystem poifs = new POIFSFileSystem(new File(args[0])); + HDGFDiagram hdgf = new HDGFDiagram(poifs)) { PrintStream ps = System.out; ps.println("Opened " + args[0]); VSDDumper vd = new VSDDumper(ps, hdgf); vd.dumpFile(); } - } + } - public void dumpFile() { + public void dumpFile() { dumpVal("Claimed document size", hdgf.getDocumentSize(), 0); ps.println(); dumpStream(hdgf.getTrailerStream(), 0); - } + } - private void dumpStream(Stream stream, int indent) { - Pointer ptr = stream.getPointer(); - dumpVal("Stream at", ptr.getOffset(), indent); - dumpVal("Type is", ptr.getType(), indent+1); - dumpVal("Format is", ptr.getFormat(), indent+1); + private void dumpStream(Stream stream, int indent) { + Pointer ptr = stream.getPointer(); + dumpVal("Stream at", ptr.getOffset(), indent); + dumpVal("Type is", ptr.getType(), indent+1); + dumpVal("Format is", ptr.getFormat(), indent+1); dumpVal("Length is", ptr.getLength(), indent+1); - if(ptr.destinationCompressed()) { - dumpVal("DC.Length is", stream._getContentsLength(), indent+1); - } - dumpVal("Compressed is", ptr.destinationCompressed(), indent+1); - dumpVal("Stream is", stream.getClass().getName(), indent+1); + if(ptr.destinationCompressed()) { + dumpVal("DC.Length is", stream._getContentsLength(), indent+1); + } + dumpVal("Compressed is", ptr.destinationCompressed(), indent+1); + dumpVal("Stream is", stream.getClass().getName(), indent+1); - byte[] db = stream._getStore()._getContents(); - String ds = (db.length >= 8) ? Arrays.toString(db) : "[]"; - dumpVal("First few bytes are", ds, indent+1); + byte[] db = stream._getStore()._getContents(); + String ds = (db.length >= 8) ? Arrays.toString(db) : "[]"; + dumpVal("First few bytes are", ds, indent+1); - if (stream instanceof PointerContainingStream) { + if (stream instanceof PointerContainingStream) { Stream[] streams = ((PointerContainingStream) stream).getPointedToStreams(); - dumpVal("Nbr of children", streams.length, indent+1); + dumpVal("Nbr of children", streams.length, indent+1); - for(Stream s : streams) { - dumpStream(s, indent+1); - } - } - if(stream instanceof ChunkStream) { + for(Stream s : streams) { + dumpStream(s, indent+1); + } + } + if(stream instanceof ChunkStream) { Chunk[] chunks = ((ChunkStream) stream).getChunks(); - dumpVal("Nbr of chunks", chunks.length, indent+1); + dumpVal("Nbr of chunks", chunks.length, indent+1); - for(Chunk chunk : chunks) { - dumpChunk(chunk, indent+1); - } - } - } + for(Chunk chunk : chunks) { + dumpChunk(chunk, indent+1); + } + } + } - private void dumpChunk(Chunk chunk, int indent) { + private void dumpChunk(Chunk chunk, int indent) { dumpVal(chunk.getName(), "", indent); dumpVal("Length is", chunk._getContents().length, indent); dumpVal("OD Size is", chunk.getOnDiskSize(), indent); @@ -110,9 +110,9 @@ public final class VSDDumper { for(Command command : commands) { dumpVal(command.getDefinition().getName(), ""+command.getValue(), indent+1); } - } + } - private void dumpVal(String label, long value, int indent) { + private void dumpVal(String label, long value, int indent) { ps.print(tabs.substring(0,indent)); ps.print(label); ps.print('\t'); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/exceptions/HDGFException.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/exceptions/HDGFException.java index c7147328fa..1958f01ea7 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/exceptions/HDGFException.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/exceptions/HDGFException.java @@ -23,11 +23,11 @@ package org.apache.poi.hdgf.exceptions; public final class HDGFException extends RuntimeException { public HDGFException() { - super(); + super(); } public HDGFException(String message) { - super(message); + super(message); } public HDGFException(String message, Throwable cause) { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/extractor/VisioTextExtractor.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/extractor/VisioTextExtractor.java index 570eaacf4c..194075fe04 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/extractor/VisioTextExtractor.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/extractor/VisioTextExtractor.java @@ -38,103 +38,103 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; * can return the text for you (example: for use with Lucene). */ public final class VisioTextExtractor implements POIOLE2TextExtractor { - private HDGFDiagram hdgf; - private boolean doCloseFilesystem = true; - - public VisioTextExtractor(HDGFDiagram hdgf) { - this.hdgf = hdgf; - } - public VisioTextExtractor(POIFSFileSystem fs) throws IOException { - this(fs.getRoot()); - } - - public VisioTextExtractor(DirectoryNode dir) throws IOException { - this(new HDGFDiagram(dir)); - } - - public VisioTextExtractor(InputStream inp) throws IOException { - this(new POIFSFileSystem(inp)); - } - - /** - * Locates all the text entries in the file, and returns their - * contents. - * - * @return An array of each Text item in the document - */ - public String[] getAllText() { - List<String> text = new ArrayList<>(); - for(Stream stream : hdgf.getTopLevelStreams()) { - findText(stream, text); - } - return text.toArray(new String[0]); - } - private void findText(Stream stream, List<String> text) { - if(stream instanceof PointerContainingStream) { - PointerContainingStream ps = (PointerContainingStream)stream; - for(final Stream substream : ps.getPointedToStreams()) { - findText(substream, text); - } - } - if(stream instanceof ChunkStream) { - ChunkStream cs = (ChunkStream)stream; - for(final Chunk chunk : cs.getChunks()) { - if(chunk != null && - chunk.getName() != null && - "Text".equals(chunk.getName()) && - chunk.getCommands().length > 0) { - - // First command - Command cmd = chunk.getCommands()[0]; - if(cmd != null && cmd.getValue() != null) { - // Capture the text, as long as it isn't - // simply an empty string - String str = cmd.getValue().toString(); - if (!(str.isEmpty() || "\n".equals(str))) { - text.add( str ); - } - } - } - } - } - } - - /** - * Returns the textual contents of the file. - * Each textual object's text will be separated - * by a newline - * - * @return All text contained in this document, separated by <code>\n</code> - */ - @Override - public String getText() { - StringBuilder text = new StringBuilder(); - for(String t : getAllText()) { - text.append(t); - if(!t.endsWith("\r") && !t.endsWith("\n")) { - text.append('\n'); - } - } - return text.toString(); - } - - @Override - public HDGFDiagram getDocument() { - return hdgf; - } - - @Override - public void setCloseFilesystem(boolean doCloseFilesystem) { - this.doCloseFilesystem = doCloseFilesystem; - } - - @Override - public boolean isCloseFilesystem() { - return doCloseFilesystem; - } - - @Override - public HDGFDiagram getFilesystem() { - return hdgf; - } + private HDGFDiagram hdgf; + private boolean doCloseFilesystem = true; + + public VisioTextExtractor(HDGFDiagram hdgf) { + this.hdgf = hdgf; + } + public VisioTextExtractor(POIFSFileSystem fs) throws IOException { + this(fs.getRoot()); + } + + public VisioTextExtractor(DirectoryNode dir) throws IOException { + this(new HDGFDiagram(dir)); + } + + public VisioTextExtractor(InputStream inp) throws IOException { + this(new POIFSFileSystem(inp)); + } + + /** + * Locates all the text entries in the file, and returns their + * contents. + * + * @return An array of each Text item in the document + */ + public String[] getAllText() { + List<String> text = new ArrayList<>(); + for(Stream stream : hdgf.getTopLevelStreams()) { + findText(stream, text); + } + return text.toArray(new String[0]); + } + private void findText(Stream stream, List<String> text) { + if(stream instanceof PointerContainingStream) { + PointerContainingStream ps = (PointerContainingStream)stream; + for(final Stream substream : ps.getPointedToStreams()) { + findText(substream, text); + } + } + if(stream instanceof ChunkStream) { + ChunkStream cs = (ChunkStream)stream; + for(final Chunk chunk : cs.getChunks()) { + if(chunk != null && + chunk.getName() != null && + "Text".equals(chunk.getName()) && + chunk.getCommands().length > 0) { + + // First command + Command cmd = chunk.getCommands()[0]; + if(cmd != null && cmd.getValue() != null) { + // Capture the text, as long as it isn't + // simply an empty string + String str = cmd.getValue().toString(); + if (!(str.isEmpty() || "\n".equals(str))) { + text.add( str ); + } + } + } + } + } + } + + /** + * Returns the textual contents of the file. + * Each textual object's text will be separated + * by a newline + * + * @return All text contained in this document, separated by <code>\n</code> + */ + @Override + public String getText() { + StringBuilder text = new StringBuilder(); + for(String t : getAllText()) { + text.append(t); + if(!t.endsWith("\r") && !t.endsWith("\n")) { + text.append('\n'); + } + } + return text.toString(); + } + + @Override + public HDGFDiagram getDocument() { + return hdgf; + } + + @Override + public void setCloseFilesystem(boolean doCloseFilesystem) { + this.doCloseFilesystem = doCloseFilesystem; + } + + @Override + public boolean isCloseFilesystem() { + return doCloseFilesystem; + } + + @Override + public HDGFDiagram getFilesystem() { + return hdgf; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/ChunkStream.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/ChunkStream.java index b977483473..b1c10ae3e7 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/ChunkStream.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/ChunkStream.java @@ -29,55 +29,55 @@ import org.apache.poi.hdgf.pointers.Pointer; import static org.apache.logging.log4j.util.Unbox.box; public final class ChunkStream extends Stream { - private static final Logger LOG = LogManager.getLogger(ChunkStream.class); - - private final ChunkFactory chunkFactory; - /** All the Chunks we contain */ - private Chunk[] chunks; - - ChunkStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory) { - super(pointer, store); - this.chunkFactory = chunkFactory; - - // For compressed stores, we require all of the data - store.copyBlockHeaderToContents(); - } - - public Chunk[] getChunks() { return chunks; } - - /** - * Process the contents of the stream out into chunks - */ - public void findChunks() { - ArrayList<Chunk> chunksA = new ArrayList<>(); - - if(getPointer().getOffset() == 0x64b3) { - int i = 0; - i++; - } - - int pos = 0; - byte[] contents = getStore().getContents(); - try { - while(pos < contents.length) { - // Ensure we have enough data to create a chunk from - int headerSize = ChunkHeader.getHeaderSize(chunkFactory.getVersion()); - if(pos+headerSize <= contents.length) { - Chunk chunk = chunkFactory.createChunk(contents, pos); - chunksA.add(chunk); - - pos += chunk.getOnDiskSize(); - } else { - LOG.atWarn().log("Needed {} bytes to create the next chunk header, but only found {} bytes, ignoring rest of data", box(headerSize),box(contents.length - pos)); - pos = contents.length; - } - } - } - catch (Exception e) - { - LOG.atError().withThrowable(e).log("Failed to create chunk at {}, ignoring rest of data.", box(pos)); - } - - chunks = chunksA.toArray(new Chunk[0]); - } + private static final Logger LOG = LogManager.getLogger(ChunkStream.class); + + private final ChunkFactory chunkFactory; + /** All the Chunks we contain */ + private Chunk[] chunks; + + ChunkStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory) { + super(pointer, store); + this.chunkFactory = chunkFactory; + + // For compressed stores, we require all of the data + store.copyBlockHeaderToContents(); + } + + public Chunk[] getChunks() { return chunks; } + + /** + * Process the contents of the stream out into chunks + */ + public void findChunks() { + ArrayList<Chunk> chunksA = new ArrayList<>(); + + if(getPointer().getOffset() == 0x64b3) { + int i = 0; + i++; + } + + int pos = 0; + byte[] contents = getStore().getContents(); + try { + while(pos < contents.length) { + // Ensure we have enough data to create a chunk from + int headerSize = ChunkHeader.getHeaderSize(chunkFactory.getVersion()); + if(pos+headerSize <= contents.length) { + Chunk chunk = chunkFactory.createChunk(contents, pos); + chunksA.add(chunk); + + pos += chunk.getOnDiskSize(); + } else { + LOG.atWarn().log("Needed {} bytes to create the next chunk header, but only found {} bytes, ignoring rest of data", box(headerSize),box(contents.length - pos)); + pos = contents.length; + } + } + } + catch (Exception e) + { + LOG.atError().withThrowable(e).log("Failed to create chunk at {}, ignoring rest of data.", box(pos)); + } + + chunks = chunksA.toArray(new Chunk[0]); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/CompressedStreamStore.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/CompressedStreamStore.java index a8bea5ccd8..031778d07b 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/CompressedStreamStore.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/CompressedStreamStore.java @@ -29,69 +29,69 @@ import org.apache.poi.util.IOUtils; */ public final class CompressedStreamStore extends StreamStore { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 64_000_000; - - /** The raw, compressed contents */ - private byte[] compressedContents; - /** - * We're not sure what this is, but it comes before the - * real contents in the de-compressed data - */ - private final byte[] blockHeader; - private boolean blockHeaderInContents; - - byte[] _getCompressedContents() { return compressedContents; } - byte[] _getBlockHeader() { return blockHeader; } - - /** - * Creates a new compressed StreamStore, which will handle - * the decompression. - */ - CompressedStreamStore(byte[] data, int offset, int length) throws IOException { - this(decompress(data,offset,length)); - compressedContents = IOUtils.safelyClone(data, offset, length, MAX_RECORD_LENGTH); - } - /** - * Handles passing the de-compressed data onto our superclass. - */ - private CompressedStreamStore(byte[][] decompressedData) { - super(decompressedData[1], 0, decompressedData[1].length); - blockHeader = decompressedData[0]; - } - - /** - * Some kinds of streams expect their 4 byte header to be - * on the front of the contents. - * They can call this to have it sorted. - */ - protected void copyBlockHeaderToContents() { - if(blockHeaderInContents) return; - - prependContentsWith(blockHeader); - blockHeaderInContents = true; - } - - - /** - * Decompresses the given data, returning it as header + contents - */ - public static byte[][] decompress(byte[] data, int offset, int length) throws IOException { - ByteArrayInputStream bais = new ByteArrayInputStream(data, offset, length); - - // Decompress - HDGFLZW lzw = new HDGFLZW(); - byte[] decompressed = lzw.decompress(bais); - - // Split into header and contents - byte[][] ret = new byte[2][]; - ret[0] = new byte[4]; - ret[1] = new byte[decompressed.length - 4]; - - System.arraycopy(decompressed, 0, ret[0], 0, 4); - System.arraycopy(decompressed, 4, ret[1], 0, ret[1].length); - - // All done - return ret; - } + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 64_000_000; + + /** The raw, compressed contents */ + private byte[] compressedContents; + /** + * We're not sure what this is, but it comes before the + * real contents in the de-compressed data + */ + private final byte[] blockHeader; + private boolean blockHeaderInContents; + + byte[] _getCompressedContents() { return compressedContents; } + byte[] _getBlockHeader() { return blockHeader; } + + /** + * Creates a new compressed StreamStore, which will handle + * the decompression. + */ + CompressedStreamStore(byte[] data, int offset, int length) throws IOException { + this(decompress(data,offset,length)); + compressedContents = IOUtils.safelyClone(data, offset, length, MAX_RECORD_LENGTH); + } + /** + * Handles passing the de-compressed data onto our superclass. + */ + private CompressedStreamStore(byte[][] decompressedData) { + super(decompressedData[1], 0, decompressedData[1].length); + blockHeader = decompressedData[0]; + } + + /** + * Some kinds of streams expect their 4 byte header to be + * on the front of the contents. + * They can call this to have it sorted. + */ + protected void copyBlockHeaderToContents() { + if(blockHeaderInContents) return; + + prependContentsWith(blockHeader); + blockHeaderInContents = true; + } + + + /** + * Decompresses the given data, returning it as header + contents + */ + public static byte[][] decompress(byte[] data, int offset, int length) throws IOException { + ByteArrayInputStream bais = new ByteArrayInputStream(data, offset, length); + + // Decompress + HDGFLZW lzw = new HDGFLZW(); + byte[] decompressed = lzw.decompress(bais); + + // Split into header and contents + byte[][] ret = new byte[2][]; + ret[0] = new byte[4]; + ret[1] = new byte[decompressed.length - 4]; + + System.arraycopy(decompressed, 0, ret[0], 0, 4); + System.arraycopy(decompressed, 4, ret[1], 0, ret[1].length); + + // All done + return ret; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/PointerContainingStream.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/PointerContainingStream.java index e7f3cf39d4..3f3192f9fc 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/PointerContainingStream.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/PointerContainingStream.java @@ -26,56 +26,56 @@ import org.apache.poi.hdgf.pointers.PointerFactory; * other data too. */ public class PointerContainingStream extends Stream { // TODO - instantiable superclass - private Pointer[] childPointers; - private Stream[] childStreams; + private Pointer[] childPointers; + private Stream[] childStreams; - private ChunkFactory chunkFactory; - private PointerFactory pointerFactory; + private ChunkFactory chunkFactory; + private PointerFactory pointerFactory; - protected PointerContainingStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory, PointerFactory pointerFactory) { - super(pointer, store); - this.chunkFactory = chunkFactory; - this.pointerFactory = pointerFactory; - - // Have the child pointers identified and created - childPointers = pointerFactory.createContainerPointers(pointer, store.getContents()); - } + protected PointerContainingStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory, PointerFactory pointerFactory) { + super(pointer, store); + this.chunkFactory = chunkFactory; + this.pointerFactory = pointerFactory; + + // Have the child pointers identified and created + childPointers = pointerFactory.createContainerPointers(pointer, store.getContents()); + } - /** - * Returns all the pointers that we contain - */ - protected Pointer[] getChildPointers() { return childPointers; } - /** - * Returns all the "child" streams. - * These are all the streams pointed to by the pointers - * that we contain. - */ - public Stream[] getPointedToStreams() { return childStreams; } + /** + * Returns all the pointers that we contain + */ + protected Pointer[] getChildPointers() { return childPointers; } + /** + * Returns all the "child" streams. + * These are all the streams pointed to by the pointers + * that we contain. + */ + public Stream[] getPointedToStreams() { return childStreams; } - /** - * Performs a recursive search, identifying the pointers we contain, - * creating the Streams for where they point to, then searching - * those if appropriate. - */ - public void findChildren(byte[] documentData) { - // For each pointer, generate the Stream it points to - childStreams = new Stream[childPointers.length]; - for(int i=0; i<childPointers.length; i++) { - Pointer ptr = childPointers[i]; - childStreams[i] = Stream.createStream(ptr, documentData, chunkFactory, pointerFactory); + /** + * Performs a recursive search, identifying the pointers we contain, + * creating the Streams for where they point to, then searching + * those if appropriate. + */ + public void findChildren(byte[] documentData) { + // For each pointer, generate the Stream it points to + childStreams = new Stream[childPointers.length]; + for(int i=0; i<childPointers.length; i++) { + Pointer ptr = childPointers[i]; + childStreams[i] = Stream.createStream(ptr, documentData, chunkFactory, pointerFactory); - // Process chunk streams into their chunks - if(childStreams[i] instanceof ChunkStream) { - ChunkStream child = (ChunkStream)childStreams[i]; - child.findChunks(); - } + // Process chunk streams into their chunks + if(childStreams[i] instanceof ChunkStream) { + ChunkStream child = (ChunkStream)childStreams[i]; + child.findChunks(); + } - // Recurse into pointer containing streams - if(childStreams[i] instanceof PointerContainingStream) { - PointerContainingStream child = - (PointerContainingStream)childStreams[i]; - child.findChildren(documentData); - } - } - } + // Recurse into pointer containing streams + if(childStreams[i] instanceof PointerContainingStream) { + PointerContainingStream child = + (PointerContainingStream)childStreams[i]; + child.findChildren(documentData); + } + } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/Stream.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/Stream.java index abd7f19e2c..b7b8ca5b62 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/Stream.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/Stream.java @@ -32,62 +32,62 @@ import org.apache.poi.hdgf.exceptions.HDGFException; * disk, but that doesn't appear to change their use. */ public abstract class Stream { - private Pointer pointer; - private StreamStore store; + private Pointer pointer; + private StreamStore store; - public Pointer getPointer() { return pointer; } - protected StreamStore getStore() { return store; } - public StreamStore _getStore() { return store; } - public int _getContentsLength() { return store.getContents().length; } + public Pointer getPointer() { return pointer; } + protected StreamStore getStore() { return store; } + public StreamStore _getStore() { return store; } + public int _getContentsLength() { return store.getContents().length; } - /** - * Creates a new Stream, having already used the pointer - * to build a store - */ - protected Stream(Pointer pointer, StreamStore store) { - this.pointer = pointer; - this.store = store; - } + /** + * Creates a new Stream, having already used the pointer + * to build a store + */ + protected Stream(Pointer pointer, StreamStore store) { + this.pointer = pointer; + this.store = store; + } - /** - * Uses the pointer to locate a Stream within the document - * data, and creates it. - * @param pointer The Pointer to create a stream for - * @param documentData The raw document data - */ - public static Stream createStream(Pointer pointer, byte[] documentData, ChunkFactory chunkFactory, PointerFactory pointerFactory) { - // Create the store - StreamStore store; - if(pointer.destinationCompressed()) { - try { - store = new CompressedStreamStore( - documentData, pointer.getOffset(), pointer.getLength() - ); - } catch(IOException e) { - // Should never occur - throw new HDGFException(e); - } - } else { - store = new StreamStore( - documentData, pointer.getOffset(), pointer.getLength() - ); - } + /** + * Uses the pointer to locate a Stream within the document + * data, and creates it. + * @param pointer The Pointer to create a stream for + * @param documentData The raw document data + */ + public static Stream createStream(Pointer pointer, byte[] documentData, ChunkFactory chunkFactory, PointerFactory pointerFactory) { + // Create the store + StreamStore store; + if(pointer.destinationCompressed()) { + try { + store = new CompressedStreamStore( + documentData, pointer.getOffset(), pointer.getLength() + ); + } catch(IOException e) { + // Should never occur + throw new HDGFException(e); + } + } else { + store = new StreamStore( + documentData, pointer.getOffset(), pointer.getLength() + ); + } - // Figure out what sort of Stream to create, create and return it - if(pointer.getType() == 20) { - return new TrailerStream(pointer, store, chunkFactory, pointerFactory); - } - else if(pointer.destinationHasPointers()) { - return new PointerContainingStream(pointer, store, chunkFactory, pointerFactory); - } - else if(pointer.destinationHasChunks()) { - return new ChunkStream(pointer, store, chunkFactory); - } - else if(pointer.destinationHasStrings()) { - return new StringsStream(pointer, store, chunkFactory); - } + // Figure out what sort of Stream to create, create and return it + if(pointer.getType() == 20) { + return new TrailerStream(pointer, store, chunkFactory, pointerFactory); + } + else if(pointer.destinationHasPointers()) { + return new PointerContainingStream(pointer, store, chunkFactory, pointerFactory); + } + else if(pointer.destinationHasChunks()) { + return new ChunkStream(pointer, store, chunkFactory); + } + else if(pointer.destinationHasStrings()) { + return new StringsStream(pointer, store, chunkFactory); + } - // Give up and return a generic one - return new UnknownStream(pointer, store); - } + // Give up and return a generic one + return new UnknownStream(pointer, store); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/StreamStore.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/StreamStore.java index fa577ad2e9..0bb639bf47 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/StreamStore.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/StreamStore.java @@ -25,26 +25,26 @@ import org.apache.poi.util.IOUtils; * In future, may also handle writing it back out again */ public class StreamStore { // TODO - instantiable superclass - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 10_000_000; - - private byte[] contents; - - /** - * Creates a new, non compressed Stream Store - */ - protected StreamStore(byte[] data, int offset, int length) { - contents = IOUtils.safelyClone(data, offset, length, MAX_RECORD_LENGTH); - } - - protected void prependContentsWith(byte[] b) { - byte[] newContents = IOUtils.safelyAllocate(contents.length + (long)b.length, MAX_RECORD_LENGTH); - System.arraycopy(b, 0, newContents, 0, b.length); - System.arraycopy(contents, 0, newContents, b.length, contents.length); - contents = newContents; - } - protected void copyBlockHeaderToContents() {} - - protected byte[] getContents() { return contents; } - public byte[] _getContents() { return contents; } + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 10_000_000; + + private byte[] contents; + + /** + * Creates a new, non compressed Stream Store + */ + protected StreamStore(byte[] data, int offset, int length) { + contents = IOUtils.safelyClone(data, offset, length, MAX_RECORD_LENGTH); + } + + protected void prependContentsWith(byte[] b) { + byte[] newContents = IOUtils.safelyAllocate(contents.length + (long)b.length, MAX_RECORD_LENGTH); + System.arraycopy(b, 0, newContents, 0, b.length); + System.arraycopy(contents, 0, newContents, b.length, contents.length); + contents = newContents; + } + protected void copyBlockHeaderToContents() {} + + protected byte[] getContents() { return contents; } + public byte[] _getContents() { return contents; } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/StringsStream.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/StringsStream.java index ac6386adc4..e02cb3ff23 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/StringsStream.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/StringsStream.java @@ -25,8 +25,8 @@ import org.apache.poi.hdgf.pointers.Pointer; * of ChunkStream, it seems */ public final class StringsStream extends Stream { - protected StringsStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory) { - super(pointer, store); -// super(pointer, store, chunkFactory); - } + protected StringsStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory) { + super(pointer, store); +// super(pointer, store, chunkFactory); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/TrailerStream.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/TrailerStream.java index 9e772c2f18..cd3c1f0884 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/TrailerStream.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/TrailerStream.java @@ -28,7 +28,7 @@ import org.apache.poi.hdgf.pointers.PointerFactory; * a special series of byte near the start of the file. */ public class TrailerStream extends PointerContainingStream { // TODO - instantiable superclass - protected TrailerStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory, PointerFactory pointerFactory) { - super(pointer, store, chunkFactory, pointerFactory); - } + protected TrailerStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory, PointerFactory pointerFactory) { + super(pointer, store, chunkFactory, pointerFactory); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/UnknownStream.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/UnknownStream.java index e08d7f93c7..3d58d71248 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/UnknownStream.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/UnknownStream.java @@ -24,7 +24,7 @@ import org.apache.poi.hdgf.pointers.Pointer; * about how to process / handle it */ public final class UnknownStream extends Stream { - protected UnknownStream(Pointer pointer, StreamStore store) { - super(pointer, store); - } + protected UnknownStream(Pointer pointer, StreamStore store) { + super(pointer, store); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherDelayStm.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherDelayStm.java index 3f4784ac4a..37ba723998 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherDelayStm.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherDelayStm.java @@ -24,9 +24,9 @@ import org.apache.poi.poifs.filesystem.DirectoryNode; * */ public final class EscherDelayStm extends EscherPart { - private static final String[] PATH = { "Escher", "EscherDelayStm", }; + private static final String[] PATH = { "Escher", "EscherDelayStm", }; - public EscherDelayStm(DirectoryNode baseDir) throws IOException { - super(baseDir, PATH); - } + public EscherDelayStm(DirectoryNode baseDir) throws IOException { + super(baseDir, PATH); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherPart.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherPart.java index 47b16b7d4e..c8de838553 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherPart.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherPart.java @@ -30,58 +30,58 @@ import org.apache.poi.util.IOUtils; */ public abstract class EscherPart extends HPBFPart { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; - private EscherRecord[] records; + private EscherRecord[] records; - /** - * Creates the Escher Part, and finds our child - * escher records - */ - public EscherPart(DirectoryNode baseDir, String[] parts) throws IOException { - super(baseDir, parts); + /** + * Creates the Escher Part, and finds our child + * escher records + */ + public EscherPart(DirectoryNode baseDir, String[] parts) throws IOException { + super(baseDir, parts); - // Now create our Escher children - DefaultEscherRecordFactory erf = - new DefaultEscherRecordFactory(); + // Now create our Escher children + DefaultEscherRecordFactory erf = + new DefaultEscherRecordFactory(); - ArrayList<EscherRecord> ec = new ArrayList<>(); + ArrayList<EscherRecord> ec = new ArrayList<>(); byte[] data = getData(); - int left = data.length; - while(left > 0) { - EscherRecord er = erf.createRecord(data, 0); - er.fillFields(data, 0, erf); - left -= er.getRecordSize(); - - ec.add(er); - } - - records = ec.toArray(new EscherRecord[0]); - } - - public EscherRecord[] getEscherRecords() { - return records; - } - - /** - * Serialises our Escher children back - * into bytes. - */ - protected void generateData() { - int size = 0; - for(int i=0; i<records.length; i++) { - size += records[i].getRecordSize(); - } + int left = data.length; + while(left > 0) { + EscherRecord er = erf.createRecord(data, 0); + er.fillFields(data, 0, erf); + left -= er.getRecordSize(); + + ec.add(er); + } + + records = ec.toArray(new EscherRecord[0]); + } + + public EscherRecord[] getEscherRecords() { + return records; + } + + /** + * Serialises our Escher children back + * into bytes. + */ + protected void generateData() { + int size = 0; + for(int i=0; i<records.length; i++) { + size += records[i].getRecordSize(); + } byte[] data = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); - size = 0; - for(int i=0; i<records.length; i++) { - int thisSize = - records[i].serialize(size, data); - size += thisSize; - } - - setData(data); - } + size = 0; + for(int i=0; i<records.length; i++) { + int thisSize = + records[i].serialize(size, data); + size += thisSize; + } + + setData(data); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherStm.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherStm.java index 07cd4c66ac..7308c3b550 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherStm.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/EscherStm.java @@ -24,8 +24,8 @@ import org.apache.poi.poifs.filesystem.DirectoryNode; * */ public final class EscherStm extends EscherPart { - private static final String[] PATH = { "Escher", "EscherStm", }; - public EscherStm(DirectoryNode baseDir) throws IOException { - super(baseDir, PATH); - } + private static final String[] PATH = { "Escher", "EscherStm", }; + public EscherStm(DirectoryNode baseDir) throws IOException { + super(baseDir, PATH); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/HPBFPart.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/HPBFPart.java index ae6e8fdad7..077598b1a5 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/HPBFPart.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/HPBFPart.java @@ -31,85 +31,85 @@ import org.apache.poi.util.IOUtils; * for all of them. */ public abstract class HPBFPart { - private byte[] data; - private final String[] path; + private byte[] data; + private final String[] path; - /** - * @param path the path to the part, eg Contents or Quill, QuillSub, CONTENTS - */ - public HPBFPart(DirectoryNode baseDir, String[] path) throws IOException { - this.path = path; + /** + * @param path the path to the part, eg Contents or Quill, QuillSub, CONTENTS + */ + public HPBFPart(DirectoryNode baseDir, String[] path) throws IOException { + this.path = path; - DirectoryNode dir = getDir(baseDir, path); - String name = path[path.length-1]; + DirectoryNode dir = getDir(baseDir, path); + String name = path[path.length-1]; - if (!dir.hasEntry(name)) { + if (!dir.hasEntry(name)) { throw new IllegalArgumentException("File invalid - failed to find document entry '" + name + "'"); - } - - // Grab the data from the part stream - try (InputStream is = dir.createDocumentInputStream(name)) { - data = IOUtils.toByteArray(is); - } - } - - private static DirectoryNode getDir(DirectoryNode baseDir, String[] path) { - DirectoryNode dir = baseDir; - for(int i=0; i<path.length-1; i++) { - try { - dir = (DirectoryNode)dir.getEntry(path[i]); - } catch (FileNotFoundException e) { - throw new IllegalArgumentException("File invalid - failed to find directory entry '" - + path[i] + "': " + e); - } - } - return dir; - } - - public void writeOut(DirectoryNode baseDir) throws IOException { - String[] path = getPath(); - - // Ensure that all parent directories exist - DirectoryNode dir = baseDir; - for(int i=0; i<path.length-1; i++) { - try { - dir = (DirectoryNode)dir.getEntry(path[i]); - } catch(FileNotFoundException e) { - dir.createDirectory(path[i]); - } - } - - // Update the byte array with the latest data - generateData(); - - // Write out - ByteArrayInputStream bais = new ByteArrayInputStream(data); - dir.createDocument(path[path.length-1], bais); - } - - /** - * Called just before writing out, to trigger - * the data byte array to be updated with the - * latest contents. - */ - protected abstract void generateData(); - - /** - * Returns the raw data that makes up - * this document part. - */ - public final byte[] getData() { - return data; - } - - protected final void setData(byte[] data) { - this.data = data.clone(); - } - - /** - * Returns - */ - public final String[] getPath() { - return path; - } + } + + // Grab the data from the part stream + try (InputStream is = dir.createDocumentInputStream(name)) { + data = IOUtils.toByteArray(is); + } + } + + private static DirectoryNode getDir(DirectoryNode baseDir, String[] path) { + DirectoryNode dir = baseDir; + for(int i=0; i<path.length-1; i++) { + try { + dir = (DirectoryNode)dir.getEntry(path[i]); + } catch (FileNotFoundException e) { + throw new IllegalArgumentException("File invalid - failed to find directory entry '" + + path[i] + "': " + e); + } + } + return dir; + } + + public void writeOut(DirectoryNode baseDir) throws IOException { + String[] path = getPath(); + + // Ensure that all parent directories exist + DirectoryNode dir = baseDir; + for(int i=0; i<path.length-1; i++) { + try { + dir = (DirectoryNode)dir.getEntry(path[i]); + } catch(FileNotFoundException e) { + dir.createDirectory(path[i]); + } + } + + // Update the byte array with the latest data + generateData(); + + // Write out + ByteArrayInputStream bais = new ByteArrayInputStream(data); + dir.createDocument(path[path.length-1], bais); + } + + /** + * Called just before writing out, to trigger + * the data byte array to be updated with the + * latest contents. + */ + protected abstract void generateData(); + + /** + * Returns the raw data that makes up + * this document part. + */ + public final byte[] getData() { + return data; + } + + protected final void setData(byte[] data) { + this.data = data.clone(); + } + + /** + * Returns + */ + public final String[] getPath() { + return path; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/MainContents.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/MainContents.java index d1c5e3ff61..9753f54c25 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/MainContents.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/MainContents.java @@ -25,14 +25,14 @@ import org.apache.poi.poifs.filesystem.DirectoryNode; * The main Contents. Not yet understood */ public final class MainContents extends HPBFPart { - private static final String[] PATH = { "Contents", }; + private static final String[] PATH = { "Contents", }; - public MainContents(DirectoryNode baseDir) throws IOException { - super(baseDir, PATH); - } + public MainContents(DirectoryNode baseDir) throws IOException { + super(baseDir, PATH); + } - protected void generateData() { - // We don't parse the contents, so - // nothing will have changed - } + protected void generateData() { + // We don't parse the contents, so + // nothing will have changed + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/QuillContents.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/QuillContents.java index 6d5b67173a..4ec6add0e9 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/QuillContents.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/QuillContents.java @@ -34,73 +34,73 @@ import org.apache.poi.util.LocaleUtil; * Read Quill Contents (/Quill/QuillSub/CONTENTS) from an HPBF (Publisher .pub) document */ public final class QuillContents extends HPBFPart { - private static final Logger LOG = LogManager.getLogger(QuillContents.class); - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; + private static final Logger LOG = LogManager.getLogger(QuillContents.class); + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; - private static final String[] PATH = { "Quill", "QuillSub", "CONTENTS", }; - private final QCBit[] bits; + private static final String[] PATH = { "Quill", "QuillSub", "CONTENTS", }; + private final QCBit[] bits; - public QuillContents(DirectoryNode baseDir) throws IOException { - super(baseDir, PATH); + public QuillContents(DirectoryNode baseDir) throws IOException { + super(baseDir, PATH); - // Now parse the first 512 bytes, and produce - // all our bits + // Now parse the first 512 bytes, and produce + // all our bits byte[] data = getData(); - // Check first 8 bytes - String f8 = new String(data, 0, 8, LocaleUtil.CHARSET_1252); - if(! f8.equals("CHNKINK ")) { - throw new IllegalArgumentException("Expecting 'CHNKINK ' but was '"+f8+"'"); - } - // Ignore the next 24, for now at least + // Check first 8 bytes + String f8 = new String(data, 0, 8, LocaleUtil.CHARSET_1252); + if(! f8.equals("CHNKINK ")) { + throw new IllegalArgumentException("Expecting 'CHNKINK ' but was '"+f8+"'"); + } + // Ignore the next 24, for now at least - // Now, parse all our QC Bits - bits = new QCBit[20]; - for(int i=0; i<20; i++) { - int offset = 0x20 + i*24; - if(data[offset] == 0x18 && data[offset+1] == 0x00) { - // Has some data - String thingType = new String(data, offset+2, 4, LocaleUtil.CHARSET_1252); - int optA = LittleEndian.getUShort(data, offset+6); - int optB = LittleEndian.getUShort(data, offset+8); - int optC = LittleEndian.getUShort(data, offset+10); - String bitType = new String(data, offset+12, 4, LocaleUtil.CHARSET_1252); - int from = (int)LittleEndian.getUInt(data, offset+16); - int len = (int)LittleEndian.getUInt(data, offset+20); + // Now, parse all our QC Bits + bits = new QCBit[20]; + for(int i=0; i<20; i++) { + int offset = 0x20 + i*24; + if(data[offset] == 0x18 && data[offset+1] == 0x00) { + // Has some data + String thingType = new String(data, offset+2, 4, LocaleUtil.CHARSET_1252); + int optA = LittleEndian.getUShort(data, offset+6); + int optB = LittleEndian.getUShort(data, offset+8); + int optC = LittleEndian.getUShort(data, offset+10); + String bitType = new String(data, offset+12, 4, LocaleUtil.CHARSET_1252); + int from = (int)LittleEndian.getUInt(data, offset+16); + int len = (int)LittleEndian.getUInt(data, offset+20); - byte[] bitData = IOUtils.safelyClone(data, from, len, MAX_RECORD_LENGTH); + byte[] bitData = IOUtils.safelyClone(data, from, len, MAX_RECORD_LENGTH); - // Create - if(bitType.equals("TEXT")) { - bits[i] = new QCTextBit(thingType, bitType, bitData); - } else if(bitType.equals("PLC ")) { - try { - bits[i] = QCPLCBit.createQCPLCBit(thingType, bitType, bitData); - } catch (ArrayIndexOutOfBoundsException e) { - // bug 60685: fall back so that the rest of the document can be read - LOG.atWarn().log("Unable to read Quill Contents PLC Bit record. Ignoring this record."); - bits[i] = new UnknownQCBit(thingType, bitType, bitData); - } - } else { - bits[i] = new UnknownQCBit(thingType, bitType, bitData); - } - bits[i].setOptA(optA); - bits[i].setOptB(optB); - bits[i].setOptC(optC); - bits[i].setDataOffset(from); - } else { - // Doesn't have data - } - } - } + // Create + if(bitType.equals("TEXT")) { + bits[i] = new QCTextBit(thingType, bitType, bitData); + } else if(bitType.equals("PLC ")) { + try { + bits[i] = QCPLCBit.createQCPLCBit(thingType, bitType, bitData); + } catch (ArrayIndexOutOfBoundsException e) { + // bug 60685: fall back so that the rest of the document can be read + LOG.atWarn().log("Unable to read Quill Contents PLC Bit record. Ignoring this record."); + bits[i] = new UnknownQCBit(thingType, bitType, bitData); + } + } else { + bits[i] = new UnknownQCBit(thingType, bitType, bitData); + } + bits[i].setOptA(optA); + bits[i].setOptB(optB); + bits[i].setOptC(optC); + bits[i].setDataOffset(from); + } else { + // Doesn't have data + } + } + } - public QCBit[] getBits() { - return bits; - } + public QCBit[] getBits() { + return bits; + } - protected void generateData() { - // TODO - throw new IllegalStateException("Not done yet!"); - } + protected void generateData() { + // TODO + throw new IllegalStateException("Not done yet!"); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCBit.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCBit.java index dddbdde5bb..8e5fb8943a 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCBit.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCBit.java @@ -21,66 +21,66 @@ package org.apache.poi.hpbf.model.qcbits; * Parent of all Quill CONTENTS bits */ public abstract class QCBit { - private String thingType; - private String bitType; - private byte[] data; + private String thingType; + private String bitType; + private byte[] data; - private int optA; - private int optB; - private int optC; + private int optA; + private int optB; + private int optC; - private int dataOffset; + private int dataOffset; - public QCBit(String thingType, String bitType, byte[] data) { - this.thingType = thingType; - this.bitType = bitType; - this.data = data.clone(); - } + public QCBit(String thingType, String bitType, byte[] data) { + this.thingType = thingType; + this.bitType = bitType; + this.data = data.clone(); + } - /** - * Returns the type of the thing, eg TEXT, FONT - * or TOKN - */ - public String getThingType() { return thingType; } - /** - * Returns the type of the bit data, eg TEXT - * or PLC - */ - public String getBitType() { return bitType; } - public final byte[] getData() { return data; } - protected final void setData(byte[] data) { - this.data = data.clone(); - } + /** + * Returns the type of the thing, eg TEXT, FONT + * or TOKN + */ + public String getThingType() { return thingType; } + /** + * Returns the type of the bit data, eg TEXT + * or PLC + */ + public String getBitType() { return bitType; } + public final byte[] getData() { return data; } + protected final void setData(byte[] data) { + this.data = data.clone(); + } - public int getOptA() { - return optA; - } - public void setOptA(int optA) { - this.optA = optA; - } + public int getOptA() { + return optA; + } + public void setOptA(int optA) { + this.optA = optA; + } - public int getOptB() { - return optB; - } - public void setOptB(int optB) { - this.optB = optB; - } + public int getOptB() { + return optB; + } + public void setOptB(int optB) { + this.optB = optB; + } - public int getOptC() { - return optC; - } - public void setOptC(int optC) { - this.optC = optC; - } + public int getOptC() { + return optC; + } + public void setOptC(int optC) { + this.optC = optC; + } - public int getDataOffset() { - return dataOffset; - } - public void setDataOffset(int offset) { - this.dataOffset = offset; - } + public int getDataOffset() { + return dataOffset; + } + public void setDataOffset(int offset) { + this.dataOffset = offset; + } - public int getLength() { - return data.length; - } + public int getLength() { + return data.length; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java index 57146192ff..a8a12a9ea0 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java @@ -26,155 +26,155 @@ import org.apache.poi.util.StringUtil; * format is determined by the type of the PLCs. */ public abstract class QCPLCBit extends QCBit { - private int numberOfPLCs; - private int typeOfPLCS; - /** - * The data which goes before the main PLC entries. - * This is apparently always made up of 2 byte - * un-signed ints.. - */ - private int[] preData; - /** The first value of each PLC, normally 4 bytes */ - private long[] plcValA; - /** The second value of each PLC, normally 4 bytes */ - private long[] plcValB; - - - private QCPLCBit(String thingType, String bitType, byte[] data) { - super(thingType, bitType, data); - - // First four bytes are the number - numberOfPLCs = (int)LittleEndian.getUInt(data, 0); - - // Next four bytes are the type - typeOfPLCS = (int)LittleEndian.getUInt(data, 4); - - // Init the arrays that we can - plcValA = new long[numberOfPLCs]; - plcValB = new long[numberOfPLCs]; - } - - - - public int getNumberOfPLCs() { - return numberOfPLCs; - } - public int getTypeOfPLCS() { - return typeOfPLCS; - } - - public int[] getPreData() { - return preData; - } - - public long[] getPlcValA() { - return plcValA; - } - public long[] getPlcValB() { - return plcValB; - } - - final void setPreData(int[] preData) { - this.preData = preData.clone(); - } - - final void setPlcValA(long[] plcValA) { + private int numberOfPLCs; + private int typeOfPLCS; + /** + * The data which goes before the main PLC entries. + * This is apparently always made up of 2 byte + * un-signed ints.. + */ + private int[] preData; + /** The first value of each PLC, normally 4 bytes */ + private long[] plcValA; + /** The second value of each PLC, normally 4 bytes */ + private long[] plcValB; + + + private QCPLCBit(String thingType, String bitType, byte[] data) { + super(thingType, bitType, data); + + // First four bytes are the number + numberOfPLCs = (int)LittleEndian.getUInt(data, 0); + + // Next four bytes are the type + typeOfPLCS = (int)LittleEndian.getUInt(data, 4); + + // Init the arrays that we can + plcValA = new long[numberOfPLCs]; + plcValB = new long[numberOfPLCs]; + } + + + + public int getNumberOfPLCs() { + return numberOfPLCs; + } + public int getTypeOfPLCS() { + return typeOfPLCS; + } + + public int[] getPreData() { + return preData; + } + + public long[] getPlcValA() { + return plcValA; + } + public long[] getPlcValB() { + return plcValB; + } + + final void setPreData(int[] preData) { + this.preData = preData.clone(); + } + + final void setPlcValA(long[] plcValA) { this.plcValA = plcValA.clone(); } - final void setPlcValB(long[] plcValB) { + final void setPlcValB(long[] plcValB) { this.plcValB = plcValB.clone(); } - - - public static QCPLCBit createQCPLCBit(String thingType, String bitType, byte[] data) { - // Grab the type - int type = (int)LittleEndian.getUInt(data, 4); - switch(type) { - case 0: - return new Type0(thingType, bitType, data); - case 4: - return new Type4(thingType, bitType, data); - case 8: - return new Type8(thingType, bitType, data); - case 12: // 0xc - return new Type12(thingType, bitType, data); - default: - throw new IllegalArgumentException("Sorry, I don't know how to deal with PLCs of type " + type); - } - } - - - /** - * Type 0 seem to be somewhat rare. They have 8 bytes of pre-data, - * then 2x 2 byte values. - */ - public static class Type0 extends QCPLCBit { - private Type0(String thingType, String bitType, byte[] data) { - super(thingType, bitType, data); - - // Grab our 4x pre-data + + + public static QCPLCBit createQCPLCBit(String thingType, String bitType, byte[] data) { + // Grab the type + int type = (int)LittleEndian.getUInt(data, 4); + switch(type) { + case 0: + return new Type0(thingType, bitType, data); + case 4: + return new Type4(thingType, bitType, data); + case 8: + return new Type8(thingType, bitType, data); + case 12: // 0xc + return new Type12(thingType, bitType, data); + default: + throw new IllegalArgumentException("Sorry, I don't know how to deal with PLCs of type " + type); + } + } + + + /** + * Type 0 seem to be somewhat rare. They have 8 bytes of pre-data, + * then 2x 2 byte values. + */ + public static class Type0 extends QCPLCBit { + private Type0(String thingType, String bitType, byte[] data) { + super(thingType, bitType, data); + + // Grab our 4x pre-data int[] preData = { LittleEndian.getUShort(data, 8 + 0), LittleEndian.getUShort(data, 8 + 2), LittleEndian.getUShort(data, 8 + 4), LittleEndian.getUShort(data, 8 + 6) }; - setPreData(preData); + setPreData(preData); // And grab the 2 byte values - int cntPlcs = getNumberOfPLCs(); + int cntPlcs = getNumberOfPLCs(); long[] plcValA = new long[cntPlcs]; long[] plcValB = new long[cntPlcs]; for(int i=0; i<cntPlcs; i++) { - plcValA[i] = LittleEndian.getUShort(data, 16+(4*i)); - plcValB[i] = LittleEndian.getUShort(data, 16+(4*i)+2); - } - setPlcValA(plcValA); + plcValA[i] = LittleEndian.getUShort(data, 16+(4*i)); + plcValB[i] = LittleEndian.getUShort(data, 16+(4*i)+2); + } + setPlcValA(plcValA); setPlcValB(plcValB); - } - } - - /** - * Type 4 is quite common. They have 8 bytes of pre-data, - * then 2x 4 byte values. - */ - public static class Type4 extends QCPLCBit { - private Type4(String thingType, String bitType, byte[] data) { - super(thingType, bitType, data); - - // Grab our 4x pre-data + } + } + + /** + * Type 4 is quite common. They have 8 bytes of pre-data, + * then 2x 4 byte values. + */ + public static class Type4 extends QCPLCBit { + private Type4(String thingType, String bitType, byte[] data) { + super(thingType, bitType, data); + + // Grab our 4x pre-data int[] preData = { LittleEndian.getUShort(data, 8 + 0), LittleEndian.getUShort(data, 8 + 2), LittleEndian.getUShort(data, 8 + 4), LittleEndian.getUShort(data, 8 + 6) }; - setPreData(preData); + setPreData(preData); - // And grab the 4 byte values + // And grab the 4 byte values int cntPlcs = getNumberOfPLCs(); long[] plcValA = new long[cntPlcs]; long[] plcValB = new long[cntPlcs]; for(int i=0; i<cntPlcs; i++) { - plcValA[i] = LittleEndian.getUInt(data, 16+(8*i)); - plcValB[i] = LittleEndian.getUInt(data, 16+(8*i)+4); - } + plcValA[i] = LittleEndian.getUInt(data, 16+(8*i)); + plcValB[i] = LittleEndian.getUInt(data, 16+(8*i)+4); + } setPlcValA(plcValA); setPlcValB(plcValB); - } - } - - /** - * Type 8 is quite common. They have 14 bytes of pre-data, - * then 2x 4 byte values. - */ - public static class Type8 extends QCPLCBit { - private Type8(String thingType, String bitType, byte[] data) { - super(thingType, bitType, data); - - // Grab our 7x pre-data + } + } + + /** + * Type 8 is quite common. They have 14 bytes of pre-data, + * then 2x 4 byte values. + */ + public static class Type8 extends QCPLCBit { + private Type8(String thingType, String bitType, byte[] data) { + super(thingType, bitType, data); + + // Grab our 7x pre-data int[] preData = { LittleEndian.getUShort(data, 8 + 0), LittleEndian.getUShort(data, 8 + 2), @@ -186,124 +186,124 @@ public abstract class QCPLCBit extends QCBit { }; setPreData(preData); - // And grab the 4 byte values + // And grab the 4 byte values int cntPlcs = getNumberOfPLCs(); long[] plcValA = new long[cntPlcs]; long[] plcValB = new long[cntPlcs]; for(int i=0; i<cntPlcs; i++) { - plcValA[i] = LittleEndian.getUInt(data, 22+(8*i)); - plcValB[i] = LittleEndian.getUInt(data, 22+(8*i)+4); - } + plcValA[i] = LittleEndian.getUInt(data, 22+(8*i)); + plcValB[i] = LittleEndian.getUInt(data, 22+(8*i)+4); + } setPlcValA(plcValA); setPlcValB(plcValB); - } - } - - /** - * Type 12 holds hyperlinks, and is very complex. - * There is normally one of these for each text - * area that contains at least one hyperlinks. - * The character offsets are relative to the start - * of the text area that this applies to. - */ - public static class Type12 extends QCPLCBit { - private String[] hyperlinks; - - private static final int oneStartsAt = 0x4c; - private static final int twoStartsAt = 0x68; - private static final int threePlusIncrement = 22; - - private Type12(String thingType, String bitType, byte[] data) { - super(thingType, bitType, data); + } + } + + /** + * Type 12 holds hyperlinks, and is very complex. + * There is normally one of these for each text + * area that contains at least one hyperlinks. + * The character offsets are relative to the start + * of the text area that this applies to. + */ + public static class Type12 extends QCPLCBit { + private String[] hyperlinks; + + private static final int oneStartsAt = 0x4c; + private static final int twoStartsAt = 0x68; + private static final int threePlusIncrement = 22; + + private Type12(String thingType, String bitType, byte[] data) { + super(thingType, bitType, data); int cntPlcs = getNumberOfPLCs(); - - // How many hyperlinks do we really have? - // (zero hyperlinks gets numberOfPLCs=1) + + // How many hyperlinks do we really have? + // (zero hyperlinks gets numberOfPLCs=1) hyperlinks = new String[data.length == 0x34 ? 0 : cntPlcs]; - // We have 4 bytes, then the start point of each - // hyperlink, then the end point of the text. + // We have 4 bytes, then the start point of each + // hyperlink, then the end point of the text. int[] preData = new int[1 + cntPlcs + 1]; - for(int i=0; i<preData.length; i++) { - preData[i] = (int)LittleEndian.getUInt(data, 8+(i*4)); - } - setPreData(preData); - - // Then we have a whole bunch of stuff, which grows - // with the number of hyperlinks - // For now, we think these are shorts - int at = 8+4+(cntPlcs*4)+4; - int until = 0x34; - if(cntPlcs == 1 && hyperlinks.length == 1) { - until = oneStartsAt; - } else if(cntPlcs >= 2) { - until = twoStartsAt + (cntPlcs-2)*threePlusIncrement; - } + for(int i=0; i<preData.length; i++) { + preData[i] = (int)LittleEndian.getUInt(data, 8+(i*4)); + } + setPreData(preData); + + // Then we have a whole bunch of stuff, which grows + // with the number of hyperlinks + // For now, we think these are shorts + int at = 8+4+(cntPlcs*4)+4; + int until = 0x34; + if(cntPlcs == 1 && hyperlinks.length == 1) { + until = oneStartsAt; + } else if(cntPlcs >= 2) { + until = twoStartsAt + (cntPlcs-2)*threePlusIncrement; + } long[] plcValA = new long[(until - at) / 2]; long[] plcValB = new long[0]; - for(int i=0; i<plcValA.length; i++) { - plcValA[i] = LittleEndian.getUShort(data, at+(i*2)); - } + for(int i=0; i<plcValA.length; i++) { + plcValA[i] = LittleEndian.getUShort(data, at+(i*2)); + } setPlcValA(plcValA); setPlcValB(plcValB); - // Finally, we have a series of lengths + hyperlinks - at = until; - for(int i=0; i<hyperlinks.length; i++) { - int len = LittleEndian.getUShort(data, at); - int first = LittleEndian.getUShort(data, at+2); - if(first == 0) { - // Crazy special case - // Length is in bytes, from the start - // Hyperlink appears to be empty - hyperlinks[i] = ""; - at += len; - } else { - // Normal case. Length is in characters - hyperlinks[i] = StringUtil.getFromUnicodeLE(data, at+2, len); - at += 2 + (2*len); - } - } - } - - /** - * Returns the number of hyperlinks, which should - * either be zero, or the number of PLC bits - */ - public int getNumberOfHyperlinks() { - return hyperlinks.length; - } - - /** - * Returns the URL of the hyperlink at the - * given index. - * @param number The hyperlink number, zero based - */ - public String getHyperlink(int number) { - return hyperlinks[number]; - } - /** - * Returns where in the text (in characters) the - * hyperlink at the given index starts - * applying to. - * This position is relative to the text area that this - * PLCBit applies to. - * @param number The hyperlink number, zero based - */ - public int getTextStartAt(int number) { - return getPreData()[1+number]; - } - /** - * Returns where in the text that this block - * of hyperlinks stops applying to. Normally, - * but not always the end of the text. - * This position is relative to the text area that this - * PLCBit applies to. - */ - public int getAllTextEndAt() { - return getPreData()[getNumberOfPLCs()+1]; - } - } + // Finally, we have a series of lengths + hyperlinks + at = until; + for(int i=0; i<hyperlinks.length; i++) { + int len = LittleEndian.getUShort(data, at); + int first = LittleEndian.getUShort(data, at+2); + if(first == 0) { + // Crazy special case + // Length is in bytes, from the start + // Hyperlink appears to be empty + hyperlinks[i] = ""; + at += len; + } else { + // Normal case. Length is in characters + hyperlinks[i] = StringUtil.getFromUnicodeLE(data, at+2, len); + at += 2 + (2*len); + } + } + } + + /** + * Returns the number of hyperlinks, which should + * either be zero, or the number of PLC bits + */ + public int getNumberOfHyperlinks() { + return hyperlinks.length; + } + + /** + * Returns the URL of the hyperlink at the + * given index. + * @param number The hyperlink number, zero based + */ + public String getHyperlink(int number) { + return hyperlinks[number]; + } + /** + * Returns where in the text (in characters) the + * hyperlink at the given index starts + * applying to. + * This position is relative to the text area that this + * PLCBit applies to. + * @param number The hyperlink number, zero based + */ + public int getTextStartAt(int number) { + return getPreData()[1+number]; + } + /** + * Returns where in the text that this block + * of hyperlinks stops applying to. Normally, + * but not always the end of the text. + * This position is relative to the text area that this + * PLCBit applies to. + */ + public int getAllTextEndAt() { + return getPreData()[getNumberOfPLCs()+1]; + } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCTextBit.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCTextBit.java index cc153708bb..61efa79df2 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCTextBit.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/QCTextBit.java @@ -25,24 +25,24 @@ import org.apache.poi.util.StringUtil; */ public final class QCTextBit extends QCBit { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; - - public QCTextBit(String thingType, String bitType, byte[] data) { - super(thingType, bitType, data); - } - - /** - * Returns the text. Note that line endings - * are \r and not \n - */ - public String getText() { - return StringUtil.getFromUnicodeLE(getData()); - } - - public void setText(String text) { + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + + public QCTextBit(String thingType, String bitType, byte[] data) { + super(thingType, bitType, data); + } + + /** + * Returns the text. Note that line endings + * are \r and not \n + */ + public String getText() { + return StringUtil.getFromUnicodeLE(getData()); + } + + public void setText(String text) { byte[] data = IOUtils.safelyAllocate(text.length() * 2L, MAX_RECORD_LENGTH); - StringUtil.putUnicodeLE(text, data, 0); - setData(data); - } + StringUtil.putUnicodeLE(text, data, 0); + setData(data); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/UnknownQCBit.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/UnknownQCBit.java index 64dae7ba11..3a75021d83 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/UnknownQCBit.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/qcbits/UnknownQCBit.java @@ -22,7 +22,7 @@ package org.apache.poi.hpbf.model.qcbits; * how to handle explicitly */ public final class UnknownQCBit extends QCBit { - public UnknownQCBit(String thingType, String bitType, byte[] data) { - super(thingType, bitType, data); - } + public UnknownQCBit(String thingType, String bitType, byte[] data) { + super(thingType, bitType, data); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/blip/DIB.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/blip/DIB.java index 1840d55409..8f30cef3ca 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/blip/DIB.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/blip/DIB.java @@ -110,7 +110,7 @@ public final class DIB extends Bitmap { int fileSize = data.length + HEADER_SIZE; int offset = fileSize - imageSize; - // specifies the size, in bytes, of the bitmap file - must add the length of the header + // specifies the size, in bytes, of the bitmap file - must add the length of the header LittleEndian.putInt(header, 2, fileSize); // Reserved; set to zero LittleEndian.putInt(header, 6, 0); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/PPDrawingTextListing.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/PPDrawingTextListing.java index d44204331a..e22611aaab 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/PPDrawingTextListing.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/PPDrawingTextListing.java @@ -33,56 +33,56 @@ import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; * searches those for text. Prints out any text it finds */ public final class PPDrawingTextListing { - public static void main(String[] args) throws IOException { - if(args.length < 1) { - System.err.println("Need to give a filename"); - System.exit(1); - } + public static void main(String[] args) throws IOException { + if(args.length < 1) { + System.err.println("Need to give a filename"); + System.exit(1); + } - try (HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0])) { + try (HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0])) { - // Find PPDrawings at any second level position - Record[] records = ss.getRecords(); - for (int i = 0; i < records.length; i++) { - Record[] children = records[i].getChildRecords(); - if (children != null && children.length != 0) { - for (int j = 0; j < children.length; j++) { - if (children[j] instanceof PPDrawing) { - System.out.println("Found PPDrawing at " + j + " in top level record " + i + " (" + records[i].getRecordType() + ")"); + // Find PPDrawings at any second level position + Record[] records = ss.getRecords(); + for (int i = 0; i < records.length; i++) { + Record[] children = records[i].getChildRecords(); + if (children != null && children.length != 0) { + for (int j = 0; j < children.length; j++) { + if (children[j] instanceof PPDrawing) { + System.out.println("Found PPDrawing at " + j + " in top level record " + i + " (" + records[i].getRecordType() + ")"); - // Look for EscherTextboxWrapper's - PPDrawing ppd = (PPDrawing) children[j]; - EscherTextboxWrapper[] wrappers = ppd.getTextboxWrappers(); - System.out.println(" Has " + wrappers.length + " textbox wrappers within"); + // Look for EscherTextboxWrapper's + PPDrawing ppd = (PPDrawing) children[j]; + EscherTextboxWrapper[] wrappers = ppd.getTextboxWrappers(); + System.out.println(" Has " + wrappers.length + " textbox wrappers within"); - // Loop over the wrappers, showing what they contain - for (int k = 0; k < wrappers.length; k++) { - EscherTextboxWrapper tbw = wrappers[k]; - System.out.println(" " + k + " has " + tbw.getChildRecords().length + " PPT atoms within"); + // Loop over the wrappers, showing what they contain + for (int k = 0; k < wrappers.length; k++) { + EscherTextboxWrapper tbw = wrappers[k]; + System.out.println(" " + k + " has " + tbw.getChildRecords().length + " PPT atoms within"); - // Loop over the records, printing the text - Record[] pptatoms = tbw.getChildRecords(); - for (Record pptatom : pptatoms) { - String text = null; - if (pptatom instanceof TextBytesAtom) { - TextBytesAtom tba = (TextBytesAtom) pptatom; - text = tba.getText(); - } - if (pptatom instanceof TextCharsAtom) { - TextCharsAtom tca = (TextCharsAtom) pptatom; - text = tca.getText(); - } + // Loop over the records, printing the text + Record[] pptatoms = tbw.getChildRecords(); + for (Record pptatom : pptatoms) { + String text = null; + if (pptatom instanceof TextBytesAtom) { + TextBytesAtom tba = (TextBytesAtom) pptatom; + text = tba.getText(); + } + if (pptatom instanceof TextCharsAtom) { + TextCharsAtom tca = (TextCharsAtom) pptatom; + text = tca.getText(); + } - if (text != null) { - text = text.replace('\r', '\n'); - System.out.println(" ''" + text + "''"); - } - } - } - } - } - } - } - } - } + if (text != null) { + text = text.replace('\r', '\n'); + System.out.println(" ''" + text + "''"); + } + } + } + } + } + } + } + } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/PPTXMLDump.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/PPTXMLDump.java index eba4115853..3dca0340d1 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/PPTXMLDump.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/PPTXMLDump.java @@ -131,7 +131,7 @@ public final class PPTXMLDump { out.write("\""); } out.write(">" + CR); - padding++; + padding++; //this check works both for Escher and PowerPoint records boolean isContainer = (info & 0x000F) == 0x000F; if (isContainer) { @@ -141,7 +141,7 @@ public final class PPTXMLDump { //dump first 100 bytes of the atom data dump(out, data, pos, Math.min(size, data.length-pos), padding, true); } - padding--; + padding--; write(out, "</"+recname + ">" + CR, padding); pos += size; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SLWTListing.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SLWTListing.java index ff42ce0a45..c3cdac64a8 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SLWTListing.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SLWTListing.java @@ -31,63 +31,63 @@ import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; * and reports how many, and what sorts of things they contain */ public final class SLWTListing { - public static void main(String[] args) throws IOException { - if(args.length < 1) { - System.err.println("Need to give a filename"); - System.exit(1); - } + public static void main(String[] args) throws IOException { + if(args.length < 1) { + System.err.println("Need to give a filename"); + System.exit(1); + } - HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); - // Find the documents, and then their SLWT - Record[] records = ss.getRecords(); - for(int i=0; i<records.length; i++) { - if(records[i] instanceof Document) { - Document doc = (Document)records[i]; - SlideListWithText[] slwts = doc.getSlideListWithTexts(); + // Find the documents, and then their SLWT + Record[] records = ss.getRecords(); + for(int i=0; i<records.length; i++) { + if(records[i] instanceof Document) { + Document doc = (Document)records[i]; + SlideListWithText[] slwts = doc.getSlideListWithTexts(); - System.out.println("Document at " + i + " had " + slwts.length + " SlideListWithTexts"); - if(slwts.length == 0) { - System.err.println("** Warning: Should have had at least 1! **"); - } - if(slwts.length > 3) { - System.err.println("** Warning: Shouldn't have more than 3!"); - } + System.out.println("Document at " + i + " had " + slwts.length + " SlideListWithTexts"); + if(slwts.length == 0) { + System.err.println("** Warning: Should have had at least 1! **"); + } + if(slwts.length > 3) { + System.err.println("** Warning: Shouldn't have more than 3!"); + } - // Check the SLWTs contain what we'd expect - for(int j=0; j<slwts.length; j++) { - SlideListWithText slwt = slwts[j]; - Record[] children = slwt.getChildRecords(); + // Check the SLWTs contain what we'd expect + for(int j=0; j<slwts.length; j++) { + SlideListWithText slwt = slwts[j]; + Record[] children = slwt.getChildRecords(); - System.out.println(" - SLWT at " + j + " had " + children.length + " children:"); + System.out.println(" - SLWT at " + j + " had " + children.length + " children:"); - // Should only have SlideAtomSets if the second one - int numSAS = slwt.getSlideAtomsSets().length; - if(j == 1) { - if(numSAS == 0) { - System.err.println(" ** 2nd SLWT didn't have any SlideAtomSets!"); - } else { - System.out.println(" - Contains " + numSAS + " SlideAtomSets"); - } - } else { - if(numSAS > 0) { - System.err.println(" ** SLWT " + j + " had " + numSAS + " SlideAtomSets! (expected 0)"); - } - } + // Should only have SlideAtomSets if the second one + int numSAS = slwt.getSlideAtomsSets().length; + if(j == 1) { + if(numSAS == 0) { + System.err.println(" ** 2nd SLWT didn't have any SlideAtomSets!"); + } else { + System.out.println(" - Contains " + numSAS + " SlideAtomSets"); + } + } else { + if(numSAS > 0) { + System.err.println(" ** SLWT " + j + " had " + numSAS + " SlideAtomSets! (expected 0)"); + } + } - // Report the first 5 children, to give a flavour - int upTo = 5; - if(children.length < 5) { upTo = children.length; } - for(int k=0; k<upTo; k++) { - Record r = children[k]; - int typeID = (int)r.getRecordType(); - String typeName = RecordTypes.forTypeID(typeID).name(); - System.out.println(" - " + typeID + " (" + typeName + ")"); - } - } - } - } - - ss.close(); - } + // Report the first 5 children, to give a flavour + int upTo = 5; + if(children.length < 5) { upTo = children.length; } + for(int k=0; k<upTo; k++) { + Record r = children[k]; + int typeID = (int)r.getRecordType(); + String typeName = RecordTypes.forTypeID(typeID).name(); + System.out.println(" - " + typeID + " (" + typeName + ")"); + } + } + } + } + + ss.close(); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SLWTTextListing.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SLWTTextListing.java index bb53698f7c..db6bffbaa8 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SLWTTextListing.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SLWTTextListing.java @@ -33,62 +33,62 @@ import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; * what it finds. */ public final class SLWTTextListing { - public static void main(String[] args) throws IOException { - if(args.length < 1) { - System.err.println("Need to give a filename"); - System.exit(1); - } + public static void main(String[] args) throws IOException { + if(args.length < 1) { + System.err.println("Need to give a filename"); + System.exit(1); + } - HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); - // Find the documents, and then their SLWT - Record[] records = ss.getRecords(); - for(int i=0; i<records.length; i++) { - if(records[i] instanceof Document) { - Record docRecord = records[i]; - Record[] docChildren = docRecord.getChildRecords(); - for(int j=0; j<docChildren.length; j++) { - if(docChildren[j] instanceof SlideListWithText) { - System.out.println("Found SLWT at pos " + j + " in the Document at " + i); - System.out.println(" Has " + docChildren[j].getChildRecords().length + " children"); + // Find the documents, and then their SLWT + Record[] records = ss.getRecords(); + for(int i=0; i<records.length; i++) { + if(records[i] instanceof Document) { + Record docRecord = records[i]; + Record[] docChildren = docRecord.getChildRecords(); + for(int j=0; j<docChildren.length; j++) { + if(docChildren[j] instanceof SlideListWithText) { + System.out.println("Found SLWT at pos " + j + " in the Document at " + i); + System.out.println(" Has " + docChildren[j].getChildRecords().length + " children"); - // Grab the SlideAtomSet's, which contain - // a SlidePersistAtom and then a bunch of text - // + related records - SlideListWithText slwt = (SlideListWithText)docChildren[j]; - SlideListWithText.SlideAtomsSet[] thisSets = slwt.getSlideAtomsSets(); - System.out.println(" Has " + thisSets.length + " AtomSets in it"); + // Grab the SlideAtomSet's, which contain + // a SlidePersistAtom and then a bunch of text + // + related records + SlideListWithText slwt = (SlideListWithText)docChildren[j]; + SlideListWithText.SlideAtomsSet[] thisSets = slwt.getSlideAtomsSets(); + System.out.println(" Has " + thisSets.length + " AtomSets in it"); - // Loop over the sets, showing what they contain - for(int k=0; k<thisSets.length; k++) { - SlidePersistAtom spa = thisSets[k].getSlidePersistAtom(); - System.out.println(" " + k + " has slide id " + spa.getSlideIdentifier() ); - System.out.println(" " + k + " has ref id " + spa.getRefID() ); + // Loop over the sets, showing what they contain + for(int k=0; k<thisSets.length; k++) { + SlidePersistAtom spa = thisSets[k].getSlidePersistAtom(); + System.out.println(" " + k + " has slide id " + spa.getSlideIdentifier() ); + System.out.println(" " + k + " has ref id " + spa.getRefID() ); - // Loop over the records, printing the text - Record[] slwtc = thisSets[k].getSlideRecords(); - for(int l=0; l<slwtc.length; l++) { - String text = null; - if(slwtc[l] instanceof TextBytesAtom) { - TextBytesAtom tba = (TextBytesAtom)slwtc[l]; - text = tba.getText(); - } - if(slwtc[l] instanceof TextCharsAtom) { - TextCharsAtom tca = (TextCharsAtom)slwtc[l]; - text = tca.getText(); - } + // Loop over the records, printing the text + Record[] slwtc = thisSets[k].getSlideRecords(); + for(int l=0; l<slwtc.length; l++) { + String text = null; + if(slwtc[l] instanceof TextBytesAtom) { + TextBytesAtom tba = (TextBytesAtom)slwtc[l]; + text = tba.getText(); + } + if(slwtc[l] instanceof TextCharsAtom) { + TextCharsAtom tca = (TextCharsAtom)slwtc[l]; + text = tca.getText(); + } - if(text != null) { - text = text.replace('\r','\n'); - System.out.println(" ''" + text + "''"); - } - } - } - } - } - } - } - - ss.close(); - } + if(text != null) { + text = text.replace('\r','\n'); + System.out.println(" ''" + text + "''"); + } + } + } + } + } + } + } + + ss.close(); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideAndNotesAtomListing.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideAndNotesAtomListing.java index a4ed6d28b6..66a2e94a18 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideAndNotesAtomListing.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideAndNotesAtomListing.java @@ -34,38 +34,38 @@ import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; * Slides, Master Slides and Notes */ public final class SlideAndNotesAtomListing { - public static void main(String[] args) throws IOException { - if(args.length < 1) { - System.err.println("Need to give a filename"); - System.exit(1); - } + public static void main(String[] args) throws IOException { + if(args.length < 1) { + System.err.println("Need to give a filename"); + System.exit(1); + } - HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); - System.out.println(); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); + System.out.println(); - // Find either Slides or Notes - Record[] records = ss.getRecords(); - for(int i=0; i<records.length; i++) { - Record r = records[i]; + // Find either Slides or Notes + Record[] records = ss.getRecords(); + for(int i=0; i<records.length; i++) { + Record r = records[i]; - // When we find them, print out their IDs - if(r instanceof Slide) { - Slide s = (Slide)r; - SlideAtom sa = s.getSlideAtom(); - System.out.println("Found Slide at " + i); - System.out.println(" Slide's master ID is " + sa.getMasterID()); - System.out.println(" Slide's notes ID is " + sa.getNotesID()); - System.out.println(); - } - if(r instanceof Notes) { - Notes n = (Notes)r; - NotesAtom na = n.getNotesAtom(); - System.out.println("Found Notes at " + i); - System.out.println(" Notes ID is " + na.getSlideID()); - System.out.println(); - } - } - - ss.close(); - } + // When we find them, print out their IDs + if(r instanceof Slide) { + Slide s = (Slide)r; + SlideAtom sa = s.getSlideAtom(); + System.out.println("Found Slide at " + i); + System.out.println(" Slide's master ID is " + sa.getMasterID()); + System.out.println(" Slide's notes ID is " + sa.getNotesID()); + System.out.println(); + } + if(r instanceof Notes) { + Notes n = (Notes)r; + NotesAtom na = n.getNotesAtom(); + System.out.println("Found Notes at " + i); + System.out.println(" Notes ID is " + na.getSlideID()); + System.out.println(); + } + } + + ss.close(); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowDumper.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowDumper.java index 230892e61f..2efe20c614 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowDumper.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowDumper.java @@ -49,10 +49,10 @@ import org.apache.poi.util.LittleEndian; */ public final class SlideShowDumper { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 100_000; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; - private byte[] docstream; + private byte[] docstream; /** Do we try to use DDF to understand the escher objects? */ private boolean ddfEscher; @@ -67,29 +67,29 @@ public final class SlideShowDumper { */ public static void main(String[] args) throws IOException { - if(args.length == 0) { - System.err.println("Usage: SlideShowDumper [-escher|-basicescher] <filename>"); - return; - } - - String filename = args[0]; - if(args.length > 1) { - filename = args[1]; - } - - try (POIFSFileSystem poifs = new POIFSFileSystem(new File(filename))) { - SlideShowDumper foo = new SlideShowDumper(poifs, System.out); - - if(args.length > 1) { - if(args[0].equalsIgnoreCase("-escher")) { - foo.setDDFEscher(true); - } else { - foo.setBasicEscher(true); - } - } - - foo.printDump(); - } + if(args.length == 0) { + System.err.println("Usage: SlideShowDumper [-escher|-basicescher] <filename>"); + return; + } + + String filename = args[0]; + if(args.length > 1) { + filename = args[1]; + } + + try (POIFSFileSystem poifs = new POIFSFileSystem(new File(filename))) { + SlideShowDumper foo = new SlideShowDumper(poifs, System.out); + + if(args.length > 1) { + if(args[0].equalsIgnoreCase("-escher")) { + foo.setDDFEscher(true); + } else { + foo.setBasicEscher(true); + } + } + + foo.printDump(); + } } /** @@ -100,19 +100,19 @@ public final class SlideShowDumper { * @throws IOException if there is a problem while parsing the document. */ public SlideShowDumper(POIFSFileSystem filesystem, PrintStream out) throws IOException { - // Grab the document stream - InputStream is = filesystem.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT); - docstream = IOUtils.toByteArray(is); - is.close(); - this.out = out; + // Grab the document stream + InputStream is = filesystem.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT); + docstream = IOUtils.toByteArray(is); + is.close(); + this.out = out; } /** * Control dumping of any Escher records found - should DDF be used? */ public void setDDFEscher(boolean grok) { - ddfEscher = grok; - basicEscher = !(grok); + ddfEscher = grok; + basicEscher = !(grok); } /** @@ -120,205 +120,205 @@ public final class SlideShowDumper { * basic groker be used? */ public void setBasicEscher(boolean grok) { - basicEscher = grok; - ddfEscher = !(grok); + basicEscher = grok; + ddfEscher = !(grok); } public void printDump() throws IOException { - // 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 ## ## ## ## + // 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) - - // 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 - // Otherwise, check the first byte. If you do a BINARY_AND on it with - // 0x0f (15) and get back 0x0f, you know it has children. Otherwise - // it doesn't - - walkTree(0,0,docstream.length); + // 01 00 E9 03 28 00 00 00 + // (type 1001 = document atom, info 00 01 normal, 28 bytes long) + + // 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 + // Otherwise, check the first byte. If you do a BINARY_AND on it with + // 0x0f (15) and get back 0x0f, you know it has children. Otherwise + // it doesn't + + walkTree(0,0,docstream.length); } public void walkTree(int depth, int startPos, int maxLen) throws IOException { - int pos = startPos; - int endPos = startPos + maxLen; - final String ind = (depth == 0) ? "%1$s" : "%1$"+depth+"s"; - while(pos <= endPos - 8) { - long type = LittleEndian.getUShort(docstream,pos+2); - long len = LittleEndian.getUInt(docstream,pos+4); - byte opt = docstream[pos]; + int pos = startPos; + int endPos = startPos + maxLen; + final String ind = (depth == 0) ? "%1$s" : "%1$"+depth+"s"; + while(pos <= endPos - 8) { + long type = LittleEndian.getUShort(docstream,pos+2); + long len = LittleEndian.getUInt(docstream,pos+4); + byte opt = docstream[pos]; - String fmt = ind+"At position %2$d (%2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)"; - out.println(String.format(Locale.ROOT, fmt, "", pos, type, len)); + String fmt = ind+"At position %2$d (%2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)"; + out.println(String.format(Locale.ROOT, fmt, "", pos, type, len)); - // See if we know about the type of it - String recordName = RecordTypes.forTypeID((short)type).name(); + // See if we know about the type of it + String recordName = RecordTypes.forTypeID((short)type).name(); - // Jump over header, and think about going on more - pos += 8; - out.println(String.format(Locale.ROOT, ind+"That's a %2$s", "", recordName)); + // Jump over header, and think about going on more + pos += 8; + out.println(String.format(Locale.ROOT, ind+"That's a %2$s", "", recordName)); - // Now check if it's a container or not - int container = opt & 0x0f; + // Now check if it's a container or not + int container = opt & 0x0f; - // BinaryTagData seems to contain records, but it - // isn't tagged as doing so. Try stepping in anyway - if(type == 5003L && opt == 0L) { - container = 0x0f; - } + // BinaryTagData seems to contain records, but it + // isn't tagged as doing so. Try stepping in anyway + if(type == 5003L && opt == 0L) { + container = 0x0f; + } out.println(); - if (type != 0L && container == 0x0f) { - if (type == 1035L || type == 1036L) { - // Special Handling of 1035=PPDrawingGroup and 1036=PPDrawing - if(ddfEscher) { - // Seems to be: - walkEscherDDF((depth+3),pos+8,(int)len-8); - } else if(basicEscher) { - walkEscherBasic((depth+3),pos+8,(int)len-8); - } - } else { - // General container record handling code - walkTree((depth+2),pos,(int)len); - } - } - - pos += (int)len; - } + if (type != 0L && container == 0x0f) { + if (type == 1035L || type == 1036L) { + // Special Handling of 1035=PPDrawingGroup and 1036=PPDrawing + if(ddfEscher) { + // Seems to be: + walkEscherDDF((depth+3),pos+8,(int)len-8); + } else if(basicEscher) { + walkEscherBasic((depth+3),pos+8,(int)len-8); + } + } else { + // General container record handling code + walkTree((depth+2),pos,(int)len); + } + } + + pos += (int)len; + } } /** * Use the DDF code to walk the Escher records */ public void walkEscherDDF(int indent, int pos, int len) { - if(len < 8) { return; } + if(len < 8) { return; } - final String ind = (indent == 0) ? "%1$s" : "%1$"+indent+"s"; + final String ind = (indent == 0) ? "%1$s" : "%1$"+indent+"s"; byte[] contents = IOUtils.safelyClone(docstream, pos, len, MAX_RECORD_LENGTH); - DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory(); - EscherRecord record = erf.createRecord(contents,0); + DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory(); + EscherRecord record = erf.createRecord(contents,0); - // For now, try filling in the fields - record.fillFields(contents,0,erf); + // For now, try filling in the fields + record.fillFields(contents,0,erf); - long atomType = LittleEndian.getUShort(contents,2); - // This lacks the 8 byte header size - long atomLen = LittleEndian.getUShort(contents,4); - // This (should) include the 8 byte header size - int recordLen = record.getRecordSize(); + long atomType = LittleEndian.getUShort(contents,2); + // This lacks the 8 byte header size + long atomLen = LittleEndian.getUShort(contents,4); + // This (should) include the 8 byte header size + int recordLen = record.getRecordSize(); String fmt = ind+"At position %2$d (%2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x) (%5$d) - record claims %6$d"; out.println(String.format(Locale.ROOT, fmt, "", pos, atomType, atomLen, atomLen+8, recordLen)); - // Check for corrupt / lying ones - if(recordLen != 8 && (recordLen != (atomLen+8))) { - out.println(String.format(Locale.ROOT, ind+"** Atom length of $2d ($3d) doesn't match record length of %4d", "", atomLen, atomLen+8, recordLen)); - } + // Check for corrupt / lying ones + if(recordLen != 8 && (recordLen != (atomLen+8))) { + out.println(String.format(Locale.ROOT, ind+"** Atom length of $2d ($3d) doesn't match record length of %4d", "", atomLen, atomLen+8, recordLen)); + } - // Print the record's details + // Print the record's details String recordStr = record.toString().replace("\n", String.format(Locale.ROOT, "\n"+ind, "")); out.println(String.format(Locale.ROOT, ind+"%2$s", "", recordStr)); if(record instanceof EscherContainerRecord) { - walkEscherDDF((indent+3), pos + 8, (int)atomLen ); - } - - // Handle records that seem to lie - if(atomType == 61451L) { - // Normally claims a size of 8 - recordLen = (int)atomLen + 8; - } - if(atomType == 61453L) { - // Returns EscherContainerRecord, but really msofbtClientTextbox - recordLen = (int)atomLen + 8; - record.fillFields( contents, 0, erf ); - if(! (record instanceof EscherTextboxRecord)) { - out.println(String.format(Locale.ROOT, ind+"%2$s", "", "** Really a msofbtClientTextbox !")); - } - } - - // Decide on what to do, based on how the lengths match up - if(recordLen == 8 && atomLen > 8 ) { - // Assume it has children, rather than being corrupted - walkEscherDDF((indent+3), pos + 8, (int)atomLen ); - - // Wind on our length + our header - pos += atomLen; - pos += 8; - len -= atomLen; - len -= 8; - } else { - // No children, wind on our real length - pos += atomLen; - pos += 8; - len -= atomLen; - len -= 8; - } - - // Move on to the next one, if we're not at the end yet - if(len >= 8) { - walkEscherDDF(indent, pos, len ); - } + walkEscherDDF((indent+3), pos + 8, (int)atomLen ); + } + + // Handle records that seem to lie + if(atomType == 61451L) { + // Normally claims a size of 8 + recordLen = (int)atomLen + 8; + } + if(atomType == 61453L) { + // Returns EscherContainerRecord, but really msofbtClientTextbox + recordLen = (int)atomLen + 8; + record.fillFields( contents, 0, erf ); + if(! (record instanceof EscherTextboxRecord)) { + out.println(String.format(Locale.ROOT, ind+"%2$s", "", "** Really a msofbtClientTextbox !")); + } + } + + // Decide on what to do, based on how the lengths match up + if(recordLen == 8 && atomLen > 8 ) { + // Assume it has children, rather than being corrupted + walkEscherDDF((indent+3), pos + 8, (int)atomLen ); + + // Wind on our length + our header + pos += atomLen; + pos += 8; + len -= atomLen; + len -= 8; + } else { + // No children, wind on our real length + pos += atomLen; + pos += 8; + len -= atomLen; + len -= 8; + } + + // Move on to the next one, if we're not at the end yet + if(len >= 8) { + walkEscherDDF(indent, pos, len ); + } } /** * Use the basic record format groking code to walk the Escher records */ public void walkEscherBasic(int indent, int pos, int len) throws IOException { - if(len < 8) { return; } + if(len < 8) { return; } - final String ind = (indent == 0) ? "%1$s" : "%1$"+indent+"s"; + final String ind = (indent == 0) ? "%1$s" : "%1$"+indent+"s"; - long type = LittleEndian.getUShort(docstream,pos+2); - long atomlen = LittleEndian.getUInt(docstream,pos+4); + long type = LittleEndian.getUShort(docstream,pos+2); + long atomlen = LittleEndian.getUInt(docstream,pos+4); - String fmt = ind+"At position %2$d ($2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)"; - out.println(String.format(Locale.ROOT, fmt, "", pos, type, atomlen)); + String fmt = ind+"At position %2$d ($2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)"; + out.println(String.format(Locale.ROOT, fmt, "", pos, type, atomlen)); - String typeName = RecordTypes.forTypeID((short)type).name(); - out.println(String.format(Locale.ROOT, ind+"%2$s", "That's an Escher Record: ", typeName)); + String typeName = RecordTypes.forTypeID((short)type).name(); + out.println(String.format(Locale.ROOT, ind+"%2$s", "That's an Escher Record: ", typeName)); - // Record specific dumps - if(type == 61453L) { - // Text Box. Print out first 8 bytes of data, then 8 4 later - HexDump.dump(docstream, 0, out, pos+8, 8); - HexDump.dump(docstream, 0, out, pos+20, 8); - out.println(); - } + // Record specific dumps + if(type == 61453L) { + // Text Box. Print out first 8 bytes of data, then 8 4 later + HexDump.dump(docstream, 0, out, pos+8, 8); + HexDump.dump(docstream, 0, out, pos+20, 8); + out.println(); + } - // Blank line before next entry - out.println(); + // Blank line before next entry + out.println(); - // Look in children if we are a container - if(type == 61443L || type == 61444L) { - walkEscherBasic((indent+3), pos+8, (int)atomlen); - } + // Look in children if we are a container + if(type == 61443L || type == 61444L) { + walkEscherBasic((indent+3), pos+8, (int)atomlen); + } - // Keep going if not yet at end - if(atomlen < len) { - int atomleni = (int)atomlen; - walkEscherBasic(indent, pos+atomleni+8, len-atomleni-8); - } + // Keep going if not yet at end + if(atomlen < len) { + int atomleni = (int)atomlen; + walkEscherBasic(indent, pos+atomleni+8, len-atomleni-8); + } } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowRecordDumper.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowRecordDumper.java index eb7a1a7ece..f1898ccd88 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowRecordDumper.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/SlideShowRecordDumper.java @@ -165,14 +165,14 @@ public final class SlideShowRecordDumper { } public void printEscherRecord(EscherRecord er, int indent) { - if (er instanceof EscherContainerRecord) { - printEscherContainerRecord( (EscherContainerRecord)er, indent ); - } else if (er instanceof EscherTextboxRecord) { - printEscherTextBox( (EscherTextboxRecord)er, indent ); - } else { - ps.print( tabs.substring(0, indent) ); - ps.println(er); - } + if (er instanceof EscherContainerRecord) { + printEscherContainerRecord( (EscherContainerRecord)er, indent ); + } else if (er instanceof EscherTextboxRecord) { + printEscherTextBox( (EscherTextboxRecord)er, indent ); + } else { + ps.print( tabs.substring(0, indent) ); + ps.println(er); + } } private void printEscherTextBox( EscherTextboxRecord tbRecord, int indent ) { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/TextStyleListing.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/TextStyleListing.java index 8df3ef0f01..dba646860a 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/TextStyleListing.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/TextStyleListing.java @@ -35,84 +35,84 @@ import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; * Having found them, it shows the contents */ public final class TextStyleListing { - public static void main(String[] args) throws IOException { - if(args.length < 1) { - System.err.println("Need to give a filename"); - System.exit(1); - } + public static void main(String[] args) throws IOException { + if(args.length < 1) { + System.err.println("Need to give a filename"); + System.exit(1); + } - try (HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0])) { - // Find the documents, and then their SLWT - Record[] records = ss.getRecords(); - for (org.apache.poi.hslf.record.Record record : records) { - if (record.getRecordType() == 1000L) { - Record[] docChildren = record.getChildRecords(); - for (Record docChild : docChildren) { - if (docChild instanceof SlideListWithText) { - Record[] slwtChildren = docChild.getChildRecords(); + try (HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0])) { + // Find the documents, and then their SLWT + Record[] records = ss.getRecords(); + for (org.apache.poi.hslf.record.Record record : records) { + if (record.getRecordType() == 1000L) { + Record[] docChildren = record.getChildRecords(); + for (Record docChild : docChildren) { + if (docChild instanceof SlideListWithText) { + Record[] slwtChildren = docChild.getChildRecords(); - int lastTextLen = -1; - for (Record slwtChild : slwtChildren) { - if (slwtChild instanceof TextCharsAtom) { - lastTextLen = ((TextCharsAtom) slwtChild).getText().length(); - } - if (slwtChild instanceof TextBytesAtom) { - lastTextLen = ((TextBytesAtom) slwtChild).getText().length(); - } + int lastTextLen = -1; + for (Record slwtChild : slwtChildren) { + if (slwtChild instanceof TextCharsAtom) { + lastTextLen = ((TextCharsAtom) slwtChild).getText().length(); + } + if (slwtChild instanceof TextBytesAtom) { + lastTextLen = ((TextBytesAtom) slwtChild).getText().length(); + } - if (slwtChild instanceof StyleTextPropAtom) { - StyleTextPropAtom stpa = (StyleTextPropAtom) slwtChild; - stpa.setParentTextSize(lastTextLen); - showStyleTextPropAtom(stpa); - } - } - } - } - } - } - } - } + if (slwtChild instanceof StyleTextPropAtom) { + StyleTextPropAtom stpa = (StyleTextPropAtom) slwtChild; + stpa.setParentTextSize(lastTextLen); + showStyleTextPropAtom(stpa); + } + } + } + } + } + } + } + } - public static void showStyleTextPropAtom(StyleTextPropAtom stpa) { - System.out.println("\nFound a StyleTextPropAtom"); + public static void showStyleTextPropAtom(StyleTextPropAtom stpa) { + System.out.println("\nFound a StyleTextPropAtom"); - List<TextPropCollection> paragraphStyles = stpa.getParagraphStyles(); - System.out.println("Contains " + paragraphStyles.size() + " paragraph styles:"); - for(int i=0; i<paragraphStyles.size(); i++) { - TextPropCollection tpc = paragraphStyles.get(i); - System.out.println(" In paragraph styling " + i + ":"); - System.out.println(" Characters covered is " + tpc.getCharactersCovered()); - showTextProps(tpc); - } + List<TextPropCollection> paragraphStyles = stpa.getParagraphStyles(); + System.out.println("Contains " + paragraphStyles.size() + " paragraph styles:"); + for(int i=0; i<paragraphStyles.size(); i++) { + TextPropCollection tpc = paragraphStyles.get(i); + System.out.println(" In paragraph styling " + i + ":"); + System.out.println(" Characters covered is " + tpc.getCharactersCovered()); + showTextProps(tpc); + } - List<TextPropCollection> charStyles = stpa.getCharacterStyles(); - System.out.println("Contains " + charStyles.size() + " character styles:"); - for(int i=0; i<charStyles.size(); i++) { - TextPropCollection tpc = charStyles.get(i); - System.out.println(" In character styling " + i + ":"); - System.out.println(" Characters covered is " + tpc.getCharactersCovered()); - showTextProps(tpc); - } - } + List<TextPropCollection> charStyles = stpa.getCharacterStyles(); + System.out.println("Contains " + charStyles.size() + " character styles:"); + for(int i=0; i<charStyles.size(); i++) { + TextPropCollection tpc = charStyles.get(i); + System.out.println(" In character styling " + i + ":"); + System.out.println(" Characters covered is " + tpc.getCharactersCovered()); + showTextProps(tpc); + } + } - public static void showTextProps(TextPropCollection tpc) { - List<TextProp> textProps = tpc.getTextPropList(); - System.out.println(" Contains " + textProps.size() + " TextProps"); - for(int i=0; i<textProps.size(); i++) { - TextProp tp = textProps.get(i); - System.out.println(" " + i + " - " + tp.getName()); - System.out.println(" = " + tp.getValue()); - System.out.println(" @ " + tp.getMask()); + public static void showTextProps(TextPropCollection tpc) { + List<TextProp> textProps = tpc.getTextPropList(); + System.out.println(" Contains " + textProps.size() + " TextProps"); + for(int i=0; i<textProps.size(); i++) { + TextProp tp = textProps.get(i); + System.out.println(" " + i + " - " + tp.getName()); + System.out.println(" = " + tp.getValue()); + System.out.println(" @ " + tp.getMask()); - if(tp instanceof BitMaskTextProp) { - BitMaskTextProp bmtp = (BitMaskTextProp)tp; - String[] subPropNames = bmtp.getSubPropNames(); - boolean[] subPropMatches = bmtp.getSubPropMatches(); - for(int j=0; j<subPropNames.length; j++) { - System.out.println(" -> " + j + " - " + subPropNames[j]); - System.out.println(" " + j + " = " + subPropMatches[j]); - } - } - } - } + if(tp instanceof BitMaskTextProp) { + BitMaskTextProp bmtp = (BitMaskTextProp)tp; + String[] subPropNames = bmtp.getSubPropNames(); + boolean[] subPropMatches = bmtp.getSubPropMatches(); + for(int j=0; j<subPropNames.length; j++) { + System.out.println(" -> " + j + " - " + subPropNames[j]); + System.out.println(" " + j + " = " + subPropMatches[j]); + } + } + } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/UserEditAndPersistListing.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/UserEditAndPersistListing.java index d17eafc346..5803b42588 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/UserEditAndPersistListing.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/dev/UserEditAndPersistListing.java @@ -35,93 +35,93 @@ import org.apache.poi.util.LittleEndian; * illuminate quite what all the offsets mean */ public final class UserEditAndPersistListing { - private static byte[] fileContents; - - public static void main(String[] args) throws IOException { - if(args.length < 1) { - System.err.println("Need to give a filename"); - System.exit(1); - } - - // Create the slideshow object, for normal working with - try (HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0])) { - fileContents = ss.getUnderlyingBytes(); - System.out.println(); - - // Find any persist ones first - int pos = 0; - for (org.apache.poi.hslf.record.Record r : ss.getRecords()) { - if (r.getRecordType() == 6001L) { - // PersistPtrFullBlock - System.out.println("Found PersistPtrFullBlock at " + pos + " (" + Integer.toHexString(pos) + ")"); - } - if (r.getRecordType() == 6002L) { - // PersistPtrIncrementalBlock - System.out.println("Found PersistPtrIncrementalBlock at " + pos + " (" + Integer.toHexString(pos) + ")"); - PersistPtrHolder pph = (PersistPtrHolder) r; - - // Check the sheet offsets - Map<Integer, Integer> sheetOffsets = pph.getSlideLocationsLookup(); - for (int id : pph.getKnownSlideIDs()) { - Integer offset = sheetOffsets.get(id); - - System.out.println(" Knows about sheet " + id); - System.out.println(" That sheet lives at " + offset); - - Record atPos = findRecordAtPos(offset); - System.out.println(" The record at that pos is of type " + atPos.getRecordType()); - System.out.println(" The record at that pos has class " + atPos.getClass().getName()); - - if (!(atPos instanceof PositionDependentRecord)) { - System.out.println(" ** The record class isn't position aware! **"); - } - } - } - - // Increase the position by the on disk size - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - r.writeOut(baos); - pos += baos.size(); - } - - System.out.println(); - - pos = 0; - // Now look for UserEditAtoms - for (org.apache.poi.hslf.record.Record r : ss.getRecords()) { - if (r instanceof UserEditAtom) { - UserEditAtom uea = (UserEditAtom) r; - System.out.println("Found UserEditAtom at " + pos + " (" + Integer.toHexString(pos) + ")"); - System.out.println(" lastUserEditAtomOffset = " + uea.getLastUserEditAtomOffset()); - System.out.println(" persistPointersOffset = " + uea.getPersistPointersOffset()); - System.out.println(" docPersistRef = " + uea.getDocPersistRef()); - System.out.println(" maxPersistWritten = " + uea.getMaxPersistWritten()); - } - - // Increase the position by the on disk size - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - r.writeOut(baos); - pos += baos.size(); - } - - System.out.println(); - - - // Query the CurrentUserAtom - CurrentUserAtom cua = ss.getCurrentUserAtom(); - System.out.println("Checking Current User Atom"); - System.out.println(" Thinks the CurrentEditOffset is " + cua.getCurrentEditOffset()); - - System.out.println(); - } - } - - - // Finds the record at a given position - public static org.apache.poi.hslf.record.Record findRecordAtPos(int pos) { - long type = LittleEndian.getUShort(fileContents, pos+2); - long rlen = LittleEndian.getUInt(fileContents, pos+4); + private static byte[] fileContents; + + public static void main(String[] args) throws IOException { + if(args.length < 1) { + System.err.println("Need to give a filename"); + System.exit(1); + } + + // Create the slideshow object, for normal working with + try (HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0])) { + fileContents = ss.getUnderlyingBytes(); + System.out.println(); + + // Find any persist ones first + int pos = 0; + for (org.apache.poi.hslf.record.Record r : ss.getRecords()) { + if (r.getRecordType() == 6001L) { + // PersistPtrFullBlock + System.out.println("Found PersistPtrFullBlock at " + pos + " (" + Integer.toHexString(pos) + ")"); + } + if (r.getRecordType() == 6002L) { + // PersistPtrIncrementalBlock + System.out.println("Found PersistPtrIncrementalBlock at " + pos + " (" + Integer.toHexString(pos) + ")"); + PersistPtrHolder pph = (PersistPtrHolder) r; + + // Check the sheet offsets + Map<Integer, Integer> sheetOffsets = pph.getSlideLocationsLookup(); + for (int id : pph.getKnownSlideIDs()) { + Integer offset = sheetOffsets.get(id); + + System.out.println(" Knows about sheet " + id); + System.out.println(" That sheet lives at " + offset); + + Record atPos = findRecordAtPos(offset); + System.out.println(" The record at that pos is of type " + atPos.getRecordType()); + System.out.println(" The record at that pos has class " + atPos.getClass().getName()); + + if (!(atPos instanceof PositionDependentRecord)) { + System.out.println(" ** The record class isn't position aware! **"); + } + } + } + + // Increase the position by the on disk size + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + r.writeOut(baos); + pos += baos.size(); + } + + System.out.println(); + + pos = 0; + // Now look for UserEditAtoms + for (org.apache.poi.hslf.record.Record r : ss.getRecords()) { + if (r instanceof UserEditAtom) { + UserEditAtom uea = (UserEditAtom) r; + System.out.println("Found UserEditAtom at " + pos + " (" + Integer.toHexString(pos) + ")"); + System.out.println(" lastUserEditAtomOffset = " + uea.getLastUserEditAtomOffset()); + System.out.println(" persistPointersOffset = " + uea.getPersistPointersOffset()); + System.out.println(" docPersistRef = " + uea.getDocPersistRef()); + System.out.println(" maxPersistWritten = " + uea.getMaxPersistWritten()); + } + + // Increase the position by the on disk size + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + r.writeOut(baos); + pos += baos.size(); + } + + System.out.println(); + + + // Query the CurrentUserAtom + CurrentUserAtom cua = ss.getCurrentUserAtom(); + System.out.println("Checking Current User Atom"); + System.out.println(" Thinks the CurrentEditOffset is " + cua.getCurrentEditOffset()); + + System.out.println(); + } + } + + + // Finds the record at a given position + public static org.apache.poi.hslf.record.Record findRecordAtPos(int pos) { + long type = LittleEndian.getUShort(fileContents, pos+2); + long rlen = LittleEndian.getUInt(fileContents, pos+4); return Record.createRecordForType(type,fileContents,pos,(int)rlen+8); - } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/CorruptPowerPointFileException.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/CorruptPowerPointFileException.java index e585f64f0a..5a8693cca5 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/CorruptPowerPointFileException.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/CorruptPowerPointFileException.java @@ -23,13 +23,13 @@ package org.apache.poi.hslf.exceptions; */ public final class CorruptPowerPointFileException extends IllegalStateException { - public CorruptPowerPointFileException(String s) { - super(s); - } + public CorruptPowerPointFileException(String s) { + super(s); + } - public CorruptPowerPointFileException(String s, Throwable t) { - super(s,t); - } + public CorruptPowerPointFileException(String s, Throwable t) { + super(s,t); + } public CorruptPowerPointFileException(Throwable t) { super(t); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java index de9d534777..f5cb99f395 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java @@ -25,13 +25,13 @@ import org.apache.poi.EncryptedDocumentException; */ public final class EncryptedPowerPointFileException extends EncryptedDocumentException { - public EncryptedPowerPointFileException(String s) { - super(s); - } - - public EncryptedPowerPointFileException(String s, Throwable t) { + public EncryptedPowerPointFileException(String s) { + super(s); + } + + public EncryptedPowerPointFileException(String s, Throwable t) { super(s, t); - } + } public EncryptedPowerPointFileException(Throwable t) { super(t); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/HSLFException.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/HSLFException.java index 061d5a8457..2d22d12c92 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/HSLFException.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/HSLFException.java @@ -23,11 +23,11 @@ package org.apache.poi.hslf.exceptions; public final class HSLFException extends RuntimeException { public HSLFException() { - super(); + super(); } public HSLFException(String message) { - super(message); + super(message); } public HSLFException(String message, Throwable cause) { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/OldPowerPointFormatException.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/OldPowerPointFormatException.java index fbb2f6d5f9..719fe9ce06 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/OldPowerPointFormatException.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/exceptions/OldPowerPointFormatException.java @@ -24,7 +24,7 @@ import org.apache.poi.OldFileFormatException; * it's too old for us. */ public class OldPowerPointFormatException extends OldFileFormatException { - public OldPowerPointFormatException(String s) { - super(s); - } + public OldPowerPointFormatException(String s) { + super(s); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/BitMaskTextProp.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/BitMaskTextProp.java index 92ab8c6b0a..25418fe8e0 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/BitMaskTextProp.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/BitMaskTextProp.java @@ -37,83 +37,83 @@ import org.apache.poi.util.GenericRecordUtil; public abstract class BitMaskTextProp extends TextProp { protected static final Logger LOG = LogManager.getLogger(BitMaskTextProp.class); - private final String[] subPropNames; - private final int[] subPropMasks; - private final boolean[] subPropMatches; - - /** Fetch the list of the names of the sub properties */ - public String[] getSubPropNames() { return subPropNames; } - /** Fetch the list of if the sub properties match or not */ - public boolean[] getSubPropMatches() { return subPropMatches; } - - - protected BitMaskTextProp(BitMaskTextProp other) { - super(other); - subPropNames = (other.subPropNames == null) ? null : other.subPropNames.clone(); - subPropMasks = (other.subPropMasks == null) ? null : other.subPropMasks.clone(); - - // The old clone implementation didn't carry over matches, but keep everything else as it was - // this is failing unit tests - // subPropMatches = (other.subPropMatches == null) ? null : new boolean[other.subPropMatches.length]; - subPropMatches = (other.subPropMatches == null) ? null : other.subPropMatches.clone(); - } - - - protected BitMaskTextProp(int sizeOfDataBlock, int maskInHeader, String overallName, String... subPropNames) { - super(sizeOfDataBlock,maskInHeader,overallName); - this.subPropNames = subPropNames; - subPropMasks = new int[subPropNames.length]; - subPropMatches = new boolean[subPropNames.length]; - - int LSB = Integer.lowestOneBit(maskInHeader); - - // Initialise the masks list - for(int i=0; i<subPropMasks.length; i++) { - subPropMasks[i] = (LSB << i); - } - } - - /** - * Calculate mask from the subPropMatches. - */ - @Override - public int getWriteMask() { - /* - * The dataValue can't be taken as a mask, as sometimes certain properties - * are explicitly set to false, i.e. the mask says the property is defined - * but in the actually nibble the property is set to false - */ - int mask = 0, i = 0; - for (int subMask : subPropMasks) { - if (subPropMatches[i++]) mask |= subMask; - } - return mask; - } - - /** - * Sets the write mask, i.e. which defines the text properties to be considered - * - * @param writeMask the mask, bit values outside the property mask range will be ignored - */ - public void setWriteMask(int writeMask) { + private final String[] subPropNames; + private final int[] subPropMasks; + private final boolean[] subPropMatches; + + /** Fetch the list of the names of the sub properties */ + public String[] getSubPropNames() { return subPropNames; } + /** Fetch the list of if the sub properties match or not */ + public boolean[] getSubPropMatches() { return subPropMatches; } + + + protected BitMaskTextProp(BitMaskTextProp other) { + super(other); + subPropNames = (other.subPropNames == null) ? null : other.subPropNames.clone(); + subPropMasks = (other.subPropMasks == null) ? null : other.subPropMasks.clone(); + + // The old clone implementation didn't carry over matches, but keep everything else as it was + // this is failing unit tests + // subPropMatches = (other.subPropMatches == null) ? null : new boolean[other.subPropMatches.length]; + subPropMatches = (other.subPropMatches == null) ? null : other.subPropMatches.clone(); + } + + + protected BitMaskTextProp(int sizeOfDataBlock, int maskInHeader, String overallName, String... subPropNames) { + super(sizeOfDataBlock,maskInHeader,overallName); + this.subPropNames = subPropNames; + subPropMasks = new int[subPropNames.length]; + subPropMatches = new boolean[subPropNames.length]; + + int LSB = Integer.lowestOneBit(maskInHeader); + + // Initialise the masks list + for(int i=0; i<subPropMasks.length; i++) { + subPropMasks[i] = (LSB << i); + } + } + + /** + * Calculate mask from the subPropMatches. + */ + @Override + public int getWriteMask() { + /* + * The dataValue can't be taken as a mask, as sometimes certain properties + * are explicitly set to false, i.e. the mask says the property is defined + * but in the actually nibble the property is set to false + */ + int mask = 0, i = 0; + for (int subMask : subPropMasks) { + if (subPropMatches[i++]) mask |= subMask; + } + return mask; + } + + /** + * Sets the write mask, i.e. which defines the text properties to be considered + * + * @param writeMask the mask, bit values outside the property mask range will be ignored + */ + public void setWriteMask(int writeMask) { int i = 0; for (int subMask : subPropMasks) { subPropMatches[i++] = ((writeMask & subMask) != 0); } - } - - /** - * Return the text property value. - * Clears all bits of the value, which are marked as unset. - * - * @return the text property value. - */ - @Override - public int getValue() { - return maskValue(super.getValue()); - } - - private int maskValue(int pVal) { + } + + /** + * Return the text property value. + * Clears all bits of the value, which are marked as unset. + * + * @return the text property value. + */ + @Override + public int getValue() { + return maskValue(super.getValue()); + } + + private int maskValue(int pVal) { int val = pVal, i = 0; for (int mask : subPropMasks) { if (!subPropMatches[i++]) { @@ -121,58 +121,58 @@ public abstract class BitMaskTextProp extends TextProp { } } return val; - } - - /** - * Set the value of the text property, and recompute the sub - * properties based on it, i.e. all unset subvalues will be cleared. - * Use {@link #setSubValue(boolean, int)} to explicitly set subvalues to {@code false}. - */ - @Override - public void setValue(int val) { - super.setValue(val); - - // Figure out the values of the sub properties - int i = 0; - for(int mask : subPropMasks) { - subPropMatches[i++] = ((val & mask) != 0); - } - } - - /** - * Convenience method to set a value with mask, without splitting it into the subvalues - */ - public void setValueWithMask(int val, int writeMask) { - setWriteMask(writeMask); - super.setValue(maskValue(val)); - if (val != super.getValue()) { - LOG.atWarn().log("Style properties of '{}' don't match mask - output will be sanitized", getName()); - LOG.atDebug().log(() -> { - StringBuilder sb = new StringBuilder("The following style attributes of the '") - .append(getName()).append("' property will be ignored:\n"); - int i=0; - for (int mask : subPropMasks) { - if (!subPropMatches[i] && (val & mask) != 0) { - sb.append(subPropNames[i]).append(","); - } - i++; - } - return new SimpleMessage(sb); - }); - } - } - - /** - * Fetch the true/false status of the subproperty with the given index - */ - public boolean getSubValue(int idx) { - return subPropMatches[idx] && ((super.getValue() & subPropMasks[idx]) != 0); - } - - /** - * Set the true/false status of the subproperty with the given index - */ - public void setSubValue(boolean value, int idx) { + } + + /** + * Set the value of the text property, and recompute the sub + * properties based on it, i.e. all unset subvalues will be cleared. + * Use {@link #setSubValue(boolean, int)} to explicitly set subvalues to {@code false}. + */ + @Override + public void setValue(int val) { + super.setValue(val); + + // Figure out the values of the sub properties + int i = 0; + for(int mask : subPropMasks) { + subPropMatches[i++] = ((val & mask) != 0); + } + } + + /** + * Convenience method to set a value with mask, without splitting it into the subvalues + */ + public void setValueWithMask(int val, int writeMask) { + setWriteMask(writeMask); + super.setValue(maskValue(val)); + if (val != super.getValue()) { + LOG.atWarn().log("Style properties of '{}' don't match mask - output will be sanitized", getName()); + LOG.atDebug().log(() -> { + StringBuilder sb = new StringBuilder("The following style attributes of the '") + .append(getName()).append("' property will be ignored:\n"); + int i=0; + for (int mask : subPropMasks) { + if (!subPropMatches[i] && (val & mask) != 0) { + sb.append(subPropNames[i]).append(","); + } + i++; + } + return new SimpleMessage(sb); + }); + } + } + + /** + * Fetch the true/false status of the subproperty with the given index + */ + public boolean getSubValue(int idx) { + return subPropMatches[idx] && ((super.getValue() & subPropMasks[idx]) != 0); + } + + /** + * Set the true/false status of the subproperty with the given index + */ + public void setSubValue(boolean value, int idx) { subPropMatches[idx] = true; int newVal = super.getValue(); if (value) { @@ -181,27 +181,27 @@ public abstract class BitMaskTextProp extends TextProp { newVal &= ~subPropMasks[idx]; } super.setValue(newVal); - } - - /** - * @return an identical copy of this, i.e. also the subPropMatches are copied - */ - public BitMaskTextProp cloneAll(){ - BitMaskTextProp bmtp = copy(); - if (subPropMatches != null) { - System.arraycopy(subPropMatches, 0, bmtp.subPropMatches, 0, subPropMatches.length); - } - return bmtp; } - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "base", super::getGenericProperties, - "flags", getBitsAsString(this::getValue, subPropMasks, subPropNames) - ); - } + /** + * @return an identical copy of this, i.e. also the subPropMatches are copied + */ + public BitMaskTextProp cloneAll(){ + BitMaskTextProp bmtp = copy(); + if (subPropMatches != null) { + System.arraycopy(subPropMatches, 0, bmtp.subPropMatches, 0, subPropMatches.length); + } + return bmtp; + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "base", super::getGenericProperties, + "flags", getBitsAsString(this::getValue, subPropMasks, subPropNames) + ); + } - @Override - public abstract BitMaskTextProp copy(); + @Override + public abstract BitMaskTextProp copy(); }
\ No newline at end of file diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java index 4b7046626e..741e282738 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java @@ -22,44 +22,44 @@ package org.apache.poi.hslf.model.textproperties; * handles bold/italic/underline etc. */ public class CharFlagsTextProp extends BitMaskTextProp { - public static final int BOLD_IDX = 0; - public static final int ITALIC_IDX = 1; - public static final int UNDERLINE_IDX = 2; - public static final int SHADOW_IDX = 4; - public static final int STRIKETHROUGH_IDX = 8; - public static final int RELIEF_IDX = 9; - public static final int RESET_NUMBERING_IDX = 10; - public static final int ENABLE_NUMBERING_1_IDX = 11; - public static final int ENABLE_NUMBERING_2_IDX = 12; + public static final int BOLD_IDX = 0; + public static final int ITALIC_IDX = 1; + public static final int UNDERLINE_IDX = 2; + public static final int SHADOW_IDX = 4; + public static final int STRIKETHROUGH_IDX = 8; + public static final int RELIEF_IDX = 9; + public static final int RESET_NUMBERING_IDX = 10; + public static final int ENABLE_NUMBERING_1_IDX = 11; + public static final int ENABLE_NUMBERING_2_IDX = 12; public static final String NAME = "char_flags"; - public CharFlagsTextProp() { - super(2, 0xffff, NAME, - "bold", // 0x0001 A bit that specifies whether the characters are bold. - "italic", // 0x0002 A bit that specifies whether the characters are italicized. - "underline", // 0x0004 A bit that specifies whether the characters are underlined. - "unused1", // 0x0008 Undefined and MUST be ignored. - "shadow", // 0x0010 A bit that specifies whether the characters have a shadow effect. - "fehint", // 0x0020 A bit that specifies whether characters originated from double-byte input. - "unused2", // 0x0040 Undefined and MUST be ignored. - "kumi", // 0x0080 A bit that specifies whether Kumimoji are used for vertical text. - "strikethrough", // 0x0100 aka "unused3" - sometimes contains the strikethrough flag - "emboss", // 0x0200 A bit that specifies whether the characters are embossed. + public CharFlagsTextProp() { + super(2, 0xffff, NAME, + "bold", // 0x0001 A bit that specifies whether the characters are bold. + "italic", // 0x0002 A bit that specifies whether the characters are italicized. + "underline", // 0x0004 A bit that specifies whether the characters are underlined. + "unused1", // 0x0008 Undefined and MUST be ignored. + "shadow", // 0x0010 A bit that specifies whether the characters have a shadow effect. + "fehint", // 0x0020 A bit that specifies whether characters originated from double-byte input. + "unused2", // 0x0040 Undefined and MUST be ignored. + "kumi", // 0x0080 A bit that specifies whether Kumimoji are used for vertical text. + "strikethrough", // 0x0100 aka "unused3" - sometimes contains the strikethrough flag + "emboss", // 0x0200 A bit that specifies whether the characters are embossed. "pp9rt_1", // 0x0400 An unsigned integer that specifies the run grouping of additional text properties in StyleTextProp9Atom record. "pp9rt_2", // 0x0800 "pp9rt_3", // 0x1000 "pp9rt_4", // 0x2000 "unused4_1", // 0x4000 Undefined and MUST be ignored. "unused4_2" // 0x8000 Undefined and MUST be ignored. - ); - } + ); + } - public CharFlagsTextProp(CharFlagsTextProp other) { - super(other); - } + public CharFlagsTextProp(CharFlagsTextProp other) { + super(other); + } - @Override - public CharFlagsTextProp copy() { - return new CharFlagsTextProp(this); - } + @Override + public CharFlagsTextProp copy() { + return new CharFlagsTextProp(this); + } }
\ No newline at end of file diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java index b1bf586199..e6cfea21be 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java @@ -27,45 +27,45 @@ import org.apache.poi.util.GenericRecordUtil; * Definition for the font alignment property. */ public class FontAlignmentProp extends TextProp { - public static final String NAME = "fontAlign"; - public static final int BASELINE = 0; - public static final int TOP = 1; - public static final int CENTER = 2; - public static final int BOTTOM = 3; + public static final String NAME = "fontAlign"; + public static final int BASELINE = 0; + public static final int TOP = 1; + public static final int CENTER = 2; + public static final int BOTTOM = 3; - public FontAlignmentProp() { - super(2, 0x10000, NAME); - } + public FontAlignmentProp() { + super(2, 0x10000, NAME); + } - public FontAlignmentProp(FontAlignmentProp other) { - super(other); - } + public FontAlignmentProp(FontAlignmentProp other) { + super(other); + } - public FontAlign getFontAlign() { - switch (getValue()) { - default: - return FontAlign.AUTO; - case BASELINE: - return FontAlign.BASELINE; - case TOP: - return FontAlign.TOP; - case CENTER: - return FontAlign.CENTER; - case BOTTOM: - return FontAlign.BOTTOM; - } - } + public FontAlign getFontAlign() { + switch (getValue()) { + default: + return FontAlign.AUTO; + case BASELINE: + return FontAlign.BASELINE; + case TOP: + return FontAlign.TOP; + case CENTER: + return FontAlign.CENTER; + case BOTTOM: + return FontAlign.BOTTOM; + } + } - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "base", super::getGenericProperties, - "fontAlign", this::getFontAlign - ); - } + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "base", super::getGenericProperties, + "fontAlign", this::getFontAlign + ); + } - @Override - public FontAlignmentProp copy() { - return new FontAlignmentProp(this); - } + @Override + public FontAlignmentProp copy() { + return new FontAlignmentProp(this); + } }
\ No newline at end of file diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/IndentProp.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/IndentProp.java index e62b4b9b63..59eb3cc952 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/IndentProp.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/IndentProp.java @@ -34,13 +34,13 @@ public class IndentProp implements GenericRecord { private int charactersCovered; private short indentLevel; - /** - * Generate the definition of a given text indent - */ - public IndentProp(int charactersCovered, short indentLevel) { - this.charactersCovered = charactersCovered; - this.indentLevel = indentLevel; - } + /** + * Generate the definition of a given text indent + */ + public IndentProp(int charactersCovered, short indentLevel) { + this.charactersCovered = charactersCovered; + this.indentLevel = indentLevel; + } /** Fetch the number of characters this styling applies to */ public int getCharactersCovered() { return charactersCovered; } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/ParagraphFlagsTextProp.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/ParagraphFlagsTextProp.java index 4a8b9f01d6..f55190fc33 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/ParagraphFlagsTextProp.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/ParagraphFlagsTextProp.java @@ -21,28 +21,28 @@ package org.apache.poi.hslf.model.textproperties; * Definition for the common paragraph text property bitset. */ public final class ParagraphFlagsTextProp extends BitMaskTextProp { - public static final int BULLET_IDX = 0; - public static final int BULLET_HARDFONT_IDX = 1; - public static final int BULLET_HARDCOLOR_IDX = 2; - public static final int BULLET_HARDSIZE_IDX = 4; + public static final int BULLET_IDX = 0; + public static final int BULLET_HARDFONT_IDX = 1; + public static final int BULLET_HARDCOLOR_IDX = 2; + public static final int BULLET_HARDSIZE_IDX = 4; public static final String NAME = "paragraph_flags"; - public ParagraphFlagsTextProp() { - super(2, 0xF, NAME, - "bullet", + public ParagraphFlagsTextProp() { + super(2, 0xF, NAME, + "bullet", "bullet.hardfont", - "bullet.hardcolor", + "bullet.hardcolor", "bullet.hardsize" - ); - } + ); + } - public ParagraphFlagsTextProp(ParagraphFlagsTextProp other) { - super(other); - } + public ParagraphFlagsTextProp(ParagraphFlagsTextProp other) { + super(other); + } - @Override - public ParagraphFlagsTextProp copy() { - return new ParagraphFlagsTextProp(this); - } + @Override + public ParagraphFlagsTextProp copy() { + return new ParagraphFlagsTextProp(this); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextAlignmentProp.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextAlignmentProp.java index 96c0694208..18b4f8894d 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextAlignmentProp.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextAlignmentProp.java @@ -27,82 +27,82 @@ import org.apache.poi.util.GenericRecordUtil; * Definition for the text alignment property. */ public class TextAlignmentProp extends TextProp { - /** - * For horizontal text, left aligned. - * For vertical text, top aligned. - */ + /** + * For horizontal text, left aligned. + * For vertical text, top aligned. + */ public static final int LEFT = 0; /** * For horizontal text, centered. * For vertical text, middle aligned. */ - public static final int CENTER = 1; - - /** - * For horizontal text, right aligned. - * For vertical text, bottom aligned. - */ - public static final int RIGHT = 2; - - /** - * For horizontal text, flush left and right. - * For vertical text, flush top and bottom. - */ - public static final int JUSTIFY = 3; - - /** - * Distribute space between characters. - */ - public static final int DISTRIBUTED = 4; - - /** - * Thai distribution justification. - */ - public static final int THAIDISTRIBUTED = 5; - - /** - * Kashida justify low. - */ - public static final int JUSTIFYLOW = 6; - - public TextAlignmentProp() { - super(2, 0x800, "alignment"); - } - - - public TextAlignmentProp(TextAlignmentProp other) { - super(other); - } - - public TextAlign getTextAlign() { - switch (getValue()) { - default: - case LEFT: - return TextAlign.LEFT; - case CENTER: - return TextAlign.CENTER; - case RIGHT: - return TextAlign.RIGHT; - case JUSTIFY: - return TextAlign.JUSTIFY; - case DISTRIBUTED: - return TextAlign.DIST; - case THAIDISTRIBUTED: - return TextAlign.THAI_DIST; - } - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "base", super::getGenericProperties, - "textAlign", this::getTextAlign - ); - } - - @Override - public TextAlignmentProp copy() { - return new TextAlignmentProp(this); - } + public static final int CENTER = 1; + + /** + * For horizontal text, right aligned. + * For vertical text, bottom aligned. + */ + public static final int RIGHT = 2; + + /** + * For horizontal text, flush left and right. + * For vertical text, flush top and bottom. + */ + public static final int JUSTIFY = 3; + + /** + * Distribute space between characters. + */ + public static final int DISTRIBUTED = 4; + + /** + * Thai distribution justification. + */ + public static final int THAIDISTRIBUTED = 5; + + /** + * Kashida justify low. + */ + public static final int JUSTIFYLOW = 6; + + public TextAlignmentProp() { + super(2, 0x800, "alignment"); + } + + + public TextAlignmentProp(TextAlignmentProp other) { + super(other); + } + + public TextAlign getTextAlign() { + switch (getValue()) { + default: + case LEFT: + return TextAlign.LEFT; + case CENTER: + return TextAlign.CENTER; + case RIGHT: + return TextAlign.RIGHT; + case JUSTIFY: + return TextAlign.JUSTIFY; + case DISTRIBUTED: + return TextAlign.DIST; + case THAIDISTRIBUTED: + return TextAlign.THAI_DIST; + } + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "base", super::getGenericProperties, + "textAlign", this::getTextAlign + ); + } + + @Override + public TextAlignmentProp copy() { + return new TextAlignmentProp(this); + } }
\ No newline at end of file diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextPFException9.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextPFException9.java index 8197b30890..63d0adcf06 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextPFException9.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextPFException9.java @@ -38,96 +38,96 @@ import org.apache.poi.util.LittleEndian; */ public class TextPFException9 implements GenericRecord { - private static final AutoNumberingScheme DEFAULT_AUTONUMBER_SCHEME = AutoNumberingScheme.arabicPeriod; - private static final Short DEFAULT_START_NUMBER = 1; + private static final AutoNumberingScheme DEFAULT_AUTONUMBER_SCHEME = AutoNumberingScheme.arabicPeriod; + private static final Short DEFAULT_START_NUMBER = 1; - //private final byte mask1; - //private final byte mask2; - private final byte mask3; - private final byte mask4; - private final Short bulletBlipRef; - private final Short fBulletHasAutoNumber; - private final AutoNumberingScheme autoNumberScheme; - private final Short autoNumberStartNumber; - private final int recordLength; - public TextPFException9(final byte[] source, final int startIndex) { // NOSONAR - //this.mask1 = source[startIndex]; - //this.mask2 = source[startIndex + 1]; - this.mask3 = source[startIndex + 2]; - this.mask4 = source[startIndex + 3]; - int length = 4; - int index = startIndex + 4; - if (0 == (mask3 & (byte)0x80 )) { - this.bulletBlipRef = null; - } else { - this.bulletBlipRef = LittleEndian.getShort(source, index); - index +=2; - length = 6; - } - if (0 == (mask4 & 2)) { - this.fBulletHasAutoNumber = null; - } else { - this.fBulletHasAutoNumber = LittleEndian.getShort(source, index); - index +=2; - length +=2; - } - if (0 == (mask4 & 1)) { - this.autoNumberScheme = null; - this.autoNumberStartNumber = null; - } else { - this.autoNumberScheme = AutoNumberingScheme.forNativeID(LittleEndian.getShort(source, index)); - index +=2; - this.autoNumberStartNumber = LittleEndian.getShort(source, index); - index +=2; - length +=4; - } - this.recordLength = length; - } - public Short getBulletBlipRef() { - return bulletBlipRef; - } - public Short getfBulletHasAutoNumber() { - return fBulletHasAutoNumber; - } - public AutoNumberingScheme getAutoNumberScheme() { - if (autoNumberScheme != null) { - return autoNumberScheme; - } - return hasBulletAutoNumber() ? DEFAULT_AUTONUMBER_SCHEME : null; - } + //private final byte mask1; + //private final byte mask2; + private final byte mask3; + private final byte mask4; + private final Short bulletBlipRef; + private final Short fBulletHasAutoNumber; + private final AutoNumberingScheme autoNumberScheme; + private final Short autoNumberStartNumber; + private final int recordLength; + public TextPFException9(final byte[] source, final int startIndex) { // NOSONAR + //this.mask1 = source[startIndex]; + //this.mask2 = source[startIndex + 1]; + this.mask3 = source[startIndex + 2]; + this.mask4 = source[startIndex + 3]; + int length = 4; + int index = startIndex + 4; + if (0 == (mask3 & (byte)0x80 )) { + this.bulletBlipRef = null; + } else { + this.bulletBlipRef = LittleEndian.getShort(source, index); + index +=2; + length = 6; + } + if (0 == (mask4 & 2)) { + this.fBulletHasAutoNumber = null; + } else { + this.fBulletHasAutoNumber = LittleEndian.getShort(source, index); + index +=2; + length +=2; + } + if (0 == (mask4 & 1)) { + this.autoNumberScheme = null; + this.autoNumberStartNumber = null; + } else { + this.autoNumberScheme = AutoNumberingScheme.forNativeID(LittleEndian.getShort(source, index)); + index +=2; + this.autoNumberStartNumber = LittleEndian.getShort(source, index); + index +=2; + length +=4; + } + this.recordLength = length; + } + public Short getBulletBlipRef() { + return bulletBlipRef; + } + public Short getfBulletHasAutoNumber() { + return fBulletHasAutoNumber; + } + public AutoNumberingScheme getAutoNumberScheme() { + if (autoNumberScheme != null) { + return autoNumberScheme; + } + return hasBulletAutoNumber() ? DEFAULT_AUTONUMBER_SCHEME : null; + } - public Short getAutoNumberStartNumber() { - if (autoNumberStartNumber != null) { - return autoNumberStartNumber; - } - return hasBulletAutoNumber() ? DEFAULT_START_NUMBER : null; - } + public Short getAutoNumberStartNumber() { + if (autoNumberStartNumber != null) { + return autoNumberStartNumber; + } + return hasBulletAutoNumber() ? DEFAULT_START_NUMBER : null; + } - private boolean hasBulletAutoNumber() { - final Short one = 1; - return one.equals(fBulletHasAutoNumber); - } + private boolean hasBulletAutoNumber() { + final Short one = 1; + return one.equals(fBulletHasAutoNumber); + } - public int getRecordLength() { - return recordLength; - } - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("Record length: ").append(this.recordLength).append(" bytes\n"); - sb.append("bulletBlipRef: ").append(this.bulletBlipRef).append("\n"); - sb.append("fBulletHasAutoNumber: ").append(this.fBulletHasAutoNumber).append("\n"); - sb.append("autoNumberScheme: ").append(this.autoNumberScheme).append("\n"); - sb.append("autoNumberStartNumber: ").append(this.autoNumberStartNumber).append("\n"); - return sb.toString(); - } + public int getRecordLength() { + return recordLength; + } + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("Record length: ").append(this.recordLength).append(" bytes\n"); + sb.append("bulletBlipRef: ").append(this.bulletBlipRef).append("\n"); + sb.append("fBulletHasAutoNumber: ").append(this.fBulletHasAutoNumber).append("\n"); + sb.append("autoNumberScheme: ").append(this.autoNumberScheme).append("\n"); + sb.append("autoNumberStartNumber: ").append(this.autoNumberStartNumber).append("\n"); + return sb.toString(); + } - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "bulletBlipRef", this::getBulletBlipRef, - "bulletHasAutoNumber", this::hasBulletAutoNumber, - "autoNumberScheme", this::getAutoNumberScheme, - "autoNumberStartNumber", this::getAutoNumberStartNumber - ); - } + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "bulletBlipRef", this::getBulletBlipRef, + "bulletHasAutoNumber", this::hasBulletAutoNumber, + "autoNumberScheme", this::getAutoNumberScheme, + "autoNumberStartNumber", this::getAutoNumberStartNumber + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextProp.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextProp.java index ba4eb1ecd0..eb61970be1 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextProp.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextProp.java @@ -38,79 +38,79 @@ import org.apache.poi.util.GenericRecordUtil; * TextProps is stored in the different record classes */ public class TextProp implements Duplicatable, GenericRecord { - private int sizeOfDataBlock; // Number of bytes the data part uses - private String propName; - private int dataValue; - private int maskInHeader; - - /** - * Generate the definition of a given type of text property. - */ - public TextProp(int sizeOfDataBlock, int maskInHeader, String propName) { - this.sizeOfDataBlock = sizeOfDataBlock; - this.maskInHeader = maskInHeader; - this.propName = propName; - this.dataValue = 0; - } - - /** - * Clones the property - */ - public TextProp(TextProp other) { - this.sizeOfDataBlock = other.sizeOfDataBlock; - this.maskInHeader = other.maskInHeader; - this.propName = other.propName; - this.dataValue = other.dataValue; - } - - /** - * Name of the text property - */ - public String getName() { return propName; } - - /** - * Size of the data section of the text property (2 or 4 bytes) - */ - public int getSize() { return sizeOfDataBlock; } - - /** - * Mask in the paragraph or character "contains" header field - * that indicates that this text property is present. - */ - public int getMask() { return maskInHeader; } - /** - * Get the mask that's used at write time. Only differs from - * the result of getMask() for the mask based properties - */ - public int getWriteMask() { return getMask(); } - - /** - * Fetch the value of the text property (meaning is specific to - * each different kind of text property) - */ - public int getValue() { return dataValue; } - - /** - * Set the value of the text property. - */ - public void setValue(int val) { dataValue = val; } - - /** - * Clone, eg when you want to actually make use of one of these. - */ - @Override - public TextProp copy(){ - // subclasses need to override copy() - assert(TextProp.class.equals(this.getClass())); - return new TextProp(this); - } - - @Override - public int hashCode() { - return Objects.hash(dataValue, maskInHeader, propName, sizeOfDataBlock); + private int sizeOfDataBlock; // Number of bytes the data part uses + private String propName; + private int dataValue; + private int maskInHeader; + + /** + * Generate the definition of a given type of text property. + */ + public TextProp(int sizeOfDataBlock, int maskInHeader, String propName) { + this.sizeOfDataBlock = sizeOfDataBlock; + this.maskInHeader = maskInHeader; + this.propName = propName; + this.dataValue = 0; } - @Override + /** + * Clones the property + */ + public TextProp(TextProp other) { + this.sizeOfDataBlock = other.sizeOfDataBlock; + this.maskInHeader = other.maskInHeader; + this.propName = other.propName; + this.dataValue = other.dataValue; + } + + /** + * Name of the text property + */ + public String getName() { return propName; } + + /** + * Size of the data section of the text property (2 or 4 bytes) + */ + public int getSize() { return sizeOfDataBlock; } + + /** + * Mask in the paragraph or character "contains" header field + * that indicates that this text property is present. + */ + public int getMask() { return maskInHeader; } + /** + * Get the mask that's used at write time. Only differs from + * the result of getMask() for the mask based properties + */ + public int getWriteMask() { return getMask(); } + + /** + * Fetch the value of the text property (meaning is specific to + * each different kind of text property) + */ + public int getValue() { return dataValue; } + + /** + * Set the value of the text property. + */ + public void setValue(int val) { dataValue = val; } + + /** + * Clone, eg when you want to actually make use of one of these. + */ + @Override + public TextProp copy(){ + // subclasses need to override copy() + assert(TextProp.class.equals(this.getClass())); + return new TextProp(this); + } + + @Override + public int hashCode() { + return Objects.hash(dataValue, maskInHeader, propName, sizeOfDataBlock); + } + + @Override public boolean equals(Object obj) { if (this == obj) { return true; @@ -152,13 +152,13 @@ public class TextProp implements Duplicatable, GenericRecord { return String.format(Locale.ROOT, "%s = %d (%0#"+len+"X mask / %d bytes)", getName(), getValue(), getMask(), getSize()); } - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "sizeOfDataBlock", this::getSize, - "propName", this::getName, - "dataValue", this::getValue, - "maskInHeader", this::getMask - ); - } + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "sizeOfDataBlock", this::getSize, + "propName", this::getName, + "dataValue", this::getValue, + "maskInHeader", this::getMask + ); + } }
\ No newline at end of file diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextPropCollection.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextPropCollection.java index 62c2f935f3..de90c60c8d 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextPropCollection.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/model/textproperties/TextPropCollection.java @@ -100,7 +100,7 @@ public class TextPropCollection implements GenericRecord, Duplicatable { // indentLevel is only valid for paragraph collection // if it's set to -1, it must be omitted - see 2.9.36 TextMasterStyleLevel private short indentLevel; - private final Map<String,TextProp> textProps = new HashMap<>(); + private final Map<String,TextProp> textProps = new HashMap<>(); private int maskSpecial; private final TextPropType textPropType; @@ -126,51 +126,51 @@ public class TextPropCollection implements GenericRecord, Duplicatable { return maskSpecial; } - /** Fetch the number of characters this styling applies to */ - public int getCharactersCovered() { - return charactersCovered; + /** Fetch the number of characters this styling applies to */ + public int getCharactersCovered() { + return charactersCovered; } - /** Fetch the TextProps that define this styling in the record order */ - public List<TextProp> getTextPropList() { - List<TextProp> orderedList = new ArrayList<>(); + /** Fetch the TextProps that define this styling in the record order */ + public List<TextProp> getTextPropList() { + List<TextProp> orderedList = new ArrayList<>(); for (TextProp potProp : getPotentialProperties()) { TextProp textProp = textProps.get(potProp.getName()); if (textProp != null) { orderedList.add(textProp); } } - return orderedList; + return orderedList; } - /** Fetch the TextProp with this name, or null if it isn't present */ - @SuppressWarnings("unchecked") + /** Fetch the TextProp with this name, or null if it isn't present */ + @SuppressWarnings("unchecked") public final <T extends TextProp> T findByName(String textPropName) { - return (T)textProps.get(textPropName); - } + return (T)textProps.get(textPropName); + } @SuppressWarnings("unchecked") - public final <T extends TextProp> T removeByName(String name) { - return (T)textProps.remove(name); - } - - public final TextPropType getTextPropType() { - return textPropType; - } - - private TextProp[] getPotentialProperties() { - return (textPropType == TextPropType.paragraph) ? paragraphTextPropTypes : characterTextPropTypes; - } - - /** - * Checks the paragraph or character properties for the given property name. - * Throws a HSLFException, if the name doesn't belong into this set of properties - * - * @param name the property name - * @return if found, the property template to copy from - */ + public final <T extends TextProp> T removeByName(String name) { + return (T)textProps.remove(name); + } + + public final TextPropType getTextPropType() { + return textPropType; + } + + private TextProp[] getPotentialProperties() { + return (textPropType == TextPropType.paragraph) ? paragraphTextPropTypes : characterTextPropTypes; + } + + /** + * Checks the paragraph or character properties for the given property name. + * Throws a HSLFException, if the name doesn't belong into this set of properties + * + * @param name the property name + * @return if found, the property template to copy from + */ @SuppressWarnings("unchecked") - private <T extends TextProp> T validatePropName(final String name) { + private <T extends TextProp> T validatePropName(final String name) { for (TextProp tp : getPotentialProperties()) { if (tp.getName().equals(name)) { return (T)tp; @@ -180,7 +180,7 @@ public class TextPropCollection implements GenericRecord, Duplicatable { "No TextProp with name " + name + " is defined to add from. " + "Character and paragraphs have their own properties/names."; throw new HSLFException(errStr); - } + } /** Add the TextProp with this name to the list */ @SuppressWarnings("unchecked") @@ -195,37 +195,37 @@ public class TextPropCollection implements GenericRecord, Duplicatable { return textProp; } - /** - * Add the property at the correct position. Replaces an existing property with the same name. - * - * @param textProp the property to be added - */ - public final void addProp(TextProp textProp) { - if (textProp == null) { - throw new HSLFException("TextProp must not be null"); - } - - String propName = textProp.getName(); - validatePropName(propName); - - textProps.put(propName, textProp); - } - - /** - * For an existing set of text properties, build the list of - * properties coded for in a given run of properties. - * @return the number of bytes that were used encoding the properties list - */ - public int buildTextPropList(int containsField, byte[] data, int dataOffset) { - int bytesPassed = 0; - - // For each possible entry, see if we match the mask - // If we do, decode that, save it, and shuffle on - for(TextProp tp : getPotentialProperties()) { - // Check there's still data left to read - - // Check if this property is found in the mask - if((containsField & tp.getMask()) != 0) { + /** + * Add the property at the correct position. Replaces an existing property with the same name. + * + * @param textProp the property to be added + */ + public final void addProp(TextProp textProp) { + if (textProp == null) { + throw new HSLFException("TextProp must not be null"); + } + + String propName = textProp.getName(); + validatePropName(propName); + + textProps.put(propName, textProp); + } + + /** + * For an existing set of text properties, build the list of + * properties coded for in a given run of properties. + * @return the number of bytes that were used encoding the properties list + */ + public int buildTextPropList(int containsField, byte[] data, int dataOffset) { + int bytesPassed = 0; + + // For each possible entry, see if we match the mask + // If we do, decode that, save it, and shuffle on + for(TextProp tp : getPotentialProperties()) { + // Check there's still data left to read + + // Check if this property is found in the mask + if((containsField & tp.getMask()) != 0) { if(dataOffset+bytesPassed >= data.length) { // Out of data, can't be any more properties to go // remember the mask and return @@ -233,82 +233,82 @@ public class TextPropCollection implements GenericRecord, Duplicatable { return bytesPassed; } - // Bingo, data contains this property - TextProp prop = tp.copy(); - int val = 0; - if (prop instanceof HSLFTabStopPropCollection) { + // Bingo, data contains this property + TextProp prop = tp.copy(); + int val = 0; + if (prop instanceof HSLFTabStopPropCollection) { ((HSLFTabStopPropCollection)prop).parseProperty(data, dataOffset+bytesPassed); } else if (prop.getSize() == 2) { - val = LittleEndian.getShort(data,dataOffset+bytesPassed); - } else if(prop.getSize() == 4) { - val = LittleEndian.getInt(data,dataOffset+bytesPassed); - } else if (prop.getSize() == 0) { + val = LittleEndian.getShort(data,dataOffset+bytesPassed); + } else if(prop.getSize() == 4) { + val = LittleEndian.getInt(data,dataOffset+bytesPassed); + } else if (prop.getSize() == 0) { //remember "special" bits. maskSpecial |= tp.getMask(); continue; } - if (prop instanceof BitMaskTextProp) { - ((BitMaskTextProp)prop).setValueWithMask(val, containsField); - } else if (!(prop instanceof HSLFTabStopPropCollection)) { - prop.setValue(val); - } - bytesPassed += prop.getSize(); - addProp(prop); - } - } + if (prop instanceof BitMaskTextProp) { + ((BitMaskTextProp)prop).setValueWithMask(val, containsField); + } else if (!(prop instanceof HSLFTabStopPropCollection)) { + prop.setValue(val); + } + bytesPassed += prop.getSize(); + addProp(prop); + } + } - // Return how many bytes were used - return bytesPassed; - } + // Return how many bytes were used + return bytesPassed; + } /** * Clones the given text properties */ @Override - public TextPropCollection copy() { + public TextPropCollection copy() { return new TextPropCollection(this); - } + } - /** - * Update the size of the text that this set of properties - * applies to - */ - public void updateTextSize(int textSize) { - charactersCovered = textSize; - } + /** + * Update the size of the text that this set of properties + * applies to + */ + public void updateTextSize(int textSize) { + charactersCovered = textSize; + } - /** + /** * Writes out to disk the header, and then all the properties */ public void writeOut(OutputStream o) throws IOException { writeOut(o, false); } - /** - * Writes out to disk the header, and then all the properties - */ - public void writeOut(OutputStream o, boolean isMasterStyle) throws IOException { - if (!isMasterStyle) { - // First goes the number of characters we affect - // MasterStyles don't have this field + /** + * Writes out to disk the header, and then all the properties + */ + public void writeOut(OutputStream o, boolean isMasterStyle) throws IOException { + if (!isMasterStyle) { + // First goes the number of characters we affect + // MasterStyles don't have this field Record.writeLittleEndian(charactersCovered,o); - } + } - // Then we have the indentLevel field if it's a paragraph collection - if (textPropType == TextPropType.paragraph && indentLevel > -1) { + // Then we have the indentLevel field if it's a paragraph collection + if (textPropType == TextPropType.paragraph && indentLevel > -1) { Record.writeLittleEndian(indentLevel, o); - } + } - // Then the mask field - int mask = maskSpecial; - for (TextProp textProp : textProps.values()) { + // Then the mask field + int mask = maskSpecial; + for (TextProp textProp : textProps.values()) { mask |= textProp.getWriteMask(); } Record.writeLittleEndian(mask,o); - // Then the contents of all the properties - for (TextProp textProp : getTextPropList()) { + // Then the contents of all the properties + for (TextProp textProp : getTextPropList()) { int val = textProp.getValue(); if (textProp instanceof BitMaskTextProp && textProp.getWriteMask() == 0) { // don't add empty properties, as they can't be recognized while reading @@ -320,8 +320,8 @@ public class TextPropCollection implements GenericRecord, Duplicatable { } else if (textProp instanceof HSLFTabStopPropCollection) { ((HSLFTabStopPropCollection)textProp).writeProperty(o); } - } - } + } + } public short getIndentLevel(){ return indentLevel; @@ -335,7 +335,7 @@ public class TextPropCollection implements GenericRecord, Duplicatable { } public int hashCode() { - return Objects.hash(charactersCovered,maskSpecial,indentLevel,textProps); + return Objects.hash(charactersCovered,maskSpecial,indentLevel,textProps); } /** * compares most properties apart of the covered characters length diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/AnimationInfo.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/AnimationInfo.java index 09f237280d..27872a32b2 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/AnimationInfo.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/AnimationInfo.java @@ -29,64 +29,64 @@ import static org.apache.logging.log4j.util.Unbox.box; * A container record that specifies information about animation information for a shape. */ public final class AnimationInfo extends RecordContainer { - private byte[] _header; - - // Links to our more interesting children - private AnimationInfoAtom animationAtom; - - /** - * Set things up, and find our more interesting children - */ - protected AnimationInfo(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - findInterestingChildren(); - } - - /** - * Go through our child records, picking out the ones that are - * interesting, and saving those for use by the easy helper - * methods. - */ - private void findInterestingChildren() { - - // First child should be the ExMediaAtom - final Record child = _children[0]; - if(child instanceof AnimationInfoAtom) { - animationAtom = (AnimationInfoAtom) child; - } else { - LOG.atError().log("First child record wasn't a AnimationInfoAtom, was of type {}", box(child.getRecordType())); - } - } - - /** - * Create a new AnimationInfo, with blank fields - */ - public AnimationInfo() { + private byte[] _header; + + // Links to our more interesting children + private AnimationInfoAtom animationAtom; + + /** + * Set things up, and find our more interesting children + */ + protected AnimationInfo(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + findInterestingChildren(); + } + + /** + * Go through our child records, picking out the ones that are + * interesting, and saving those for use by the easy helper + * methods. + */ + private void findInterestingChildren() { + + // First child should be the ExMediaAtom + final Record child = _children[0]; + if(child instanceof AnimationInfoAtom) { + animationAtom = (AnimationInfoAtom) child; + } else { + LOG.atError().log("First child record wasn't a AnimationInfoAtom, was of type {}", box(child.getRecordType())); + } + } + + /** + * Create a new AnimationInfo, with blank fields + */ + public AnimationInfo() { // Setup our header block - _header = new byte[8]; - _header[0] = 0x0f; // We are a container record - LittleEndian.putShort(_header, 2, (short)getRecordType()); + _header = new byte[8]; + _header[0] = 0x0f; // We are a container record + LittleEndian.putShort(_header, 2, (short)getRecordType()); _children = new org.apache.poi.hslf.record.Record[1]; - _children[0] = animationAtom = new AnimationInfoAtom(); - } - - /** - * We are of type 4103 - */ - public long getRecordType() { return RecordTypes.AnimationInfo.typeID; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],getRecordType(),_children,out); - } + _children[0] = animationAtom = new AnimationInfoAtom(); + } + + /** + * We are of type 4103 + */ + public long getRecordType() { return RecordTypes.AnimationInfo.typeID; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],getRecordType(),_children,out); + } /** * Returns the AnimationInfo diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/BinaryTagDataBlob.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/BinaryTagDataBlob.java index 2910c18fb2..61d9a3625b 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/BinaryTagDataBlob.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/BinaryTagDataBlob.java @@ -35,32 +35,32 @@ import org.apache.poi.util.LittleEndian; public final class BinaryTagDataBlob extends PositionDependentRecordContainer { - private byte[] _header; - private long _type; + private byte[] _header; + private long _type; - /** - * Create a new holder for a boring record with children, but with - * position dependent characteristics - */ - protected BinaryTagDataBlob(byte[] source, int start, int len) { - // Just grab the header, not the whole contents - _header = Arrays.copyOfRange(source, start, start+8); - _type = LittleEndian.getUShort(_header,2); + /** + * Create a new holder for a boring record with children, but with + * position dependent characteristics + */ + protected BinaryTagDataBlob(byte[] source, int start, int len) { + // Just grab the header, not the whole contents + _header = Arrays.copyOfRange(source, start, start+8); + _type = LittleEndian.getUShort(_header,2); - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - } + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + } - /** - * Return the value we were given at creation - */ - public long getRecordType() { return _type; } + /** + * Return the value we were given at creation + */ + public long getRecordType() { return _type; } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/CString.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/CString.java index f2991f02c1..0dfd545cba 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/CString.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/CString.java @@ -36,88 +36,88 @@ import org.apache.poi.util.StringUtil; public final class CString extends RecordAtom { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; - - private byte[] _header; - - /** The bytes that make up the text */ - private byte[] _text; - - /** Grabs the text. Never <code>null</code> */ - public String getText() { - return StringUtil.getFromUnicodeLE(_text); - } - - /** Updates the text in the Atom. */ - public void setText(String text) { - // Convert to little endian unicode - _text = new byte[text.length()*2]; - StringUtil.putUnicodeLE(text,_text,0); - - // Update the size (header bytes 5-8) - LittleEndian.putInt(_header,4,_text.length); - } - - /** - * Grabs the count, from the first two bytes of the header. - * The meaning of the count is specific to the type of the parent record - */ - public int getOptions() { - return LittleEndian.getShort(_header); - } - - /** - * Sets the count - * The meaning of the count is specific to the type of the parent record - */ - public void setOptions(int count) { - LittleEndian.putShort(_header, 0, (short)count); - } - - /* *************** record code follows ********************** */ - - /** - * For the CStrubg Atom - */ - protected CString(byte[] source, int start, int len) { - // Sanity Checking - if(len < 8) { len = 8; } - - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Grab the text - _text = IOUtils.safelyClone(source,start+8, len-8, MAX_RECORD_LENGTH); - } - /** - * Create an empty CString - */ - public CString() { - // 0 length header - _header = new byte[] { 0, 0, 0xBA-256, 0x0f, 0, 0, 0, 0 }; - // Empty text - _text = new byte[0]; - } - - /** - * We are of type 4026 - */ - public long getRecordType() { - return RecordTypes.CString.typeID; - } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - // Header - size or type unchanged - out.write(_header); - - // Write out our text - out.write(_text); - } + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + + private byte[] _header; + + /** The bytes that make up the text */ + private byte[] _text; + + /** Grabs the text. Never <code>null</code> */ + public String getText() { + return StringUtil.getFromUnicodeLE(_text); + } + + /** Updates the text in the Atom. */ + public void setText(String text) { + // Convert to little endian unicode + _text = new byte[text.length()*2]; + StringUtil.putUnicodeLE(text,_text,0); + + // Update the size (header bytes 5-8) + LittleEndian.putInt(_header,4,_text.length); + } + + /** + * Grabs the count, from the first two bytes of the header. + * The meaning of the count is specific to the type of the parent record + */ + public int getOptions() { + return LittleEndian.getShort(_header); + } + + /** + * Sets the count + * The meaning of the count is specific to the type of the parent record + */ + public void setOptions(int count) { + LittleEndian.putShort(_header, 0, (short)count); + } + + /* *************** record code follows ********************** */ + + /** + * For the CStrubg Atom + */ + protected CString(byte[] source, int start, int len) { + // Sanity Checking + if(len < 8) { len = 8; } + + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Grab the text + _text = IOUtils.safelyClone(source,start+8, len-8, MAX_RECORD_LENGTH); + } + /** + * Create an empty CString + */ + public CString() { + // 0 length header + _header = new byte[] { 0, 0, 0xBA-256, 0x0f, 0, 0, 0, 0 }; + // Empty text + _text = new byte[0]; + } + + /** + * We are of type 4026 + */ + public long getRecordType() { + return RecordTypes.CString.typeID; + } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + // Header - size or type unchanged + out.write(_header); + + // Write out our text + out.write(_text); + } /** * Gets a string representation of this object, primarily for debugging. @@ -127,8 +127,8 @@ public final class CString extends RecordAtom { return getText(); } - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties("text", this::getText); - } + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties("text", this::getText); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ColorSchemeAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ColorSchemeAtom.java index 7a8dc9dbf6..6664b76676 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ColorSchemeAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ColorSchemeAtom.java @@ -36,200 +36,200 @@ import org.apache.poi.util.LittleEndian; * defines the colours to be used */ public final class ColorSchemeAtom extends RecordAtom { - private static final long _type = 2032L; - - private final byte[] _header; - private int backgroundColourRGB; - private int textAndLinesColourRGB; - private int shadowsColourRGB; - private int titleTextColourRGB; - private int fillsColourRGB; - private int accentColourRGB; - private int accentAndHyperlinkColourRGB; - private int accentAndFollowingHyperlinkColourRGB; - - /** Fetch the RGB value for Background Colour */ - public int getBackgroundColourRGB() { return backgroundColourRGB; } - /** Set the RGB value for Background Colour */ - public void setBackgroundColourRGB(int rgb) { backgroundColourRGB = rgb; } - - /** Fetch the RGB value for Text And Lines Colour */ - public int getTextAndLinesColourRGB() { return textAndLinesColourRGB; } - /** Set the RGB value for Text And Lines Colour */ - public void setTextAndLinesColourRGB(int rgb) { textAndLinesColourRGB = rgb; } - - /** Fetch the RGB value for Shadows Colour */ - public int getShadowsColourRGB() { return shadowsColourRGB; } - /** Set the RGB value for Shadows Colour */ - public void setShadowsColourRGB(int rgb) { shadowsColourRGB = rgb; } - - /** Fetch the RGB value for Title Text Colour */ - public int getTitleTextColourRGB() { return titleTextColourRGB; } - /** Set the RGB value for Title Text Colour */ - public void setTitleTextColourRGB(int rgb) { titleTextColourRGB = rgb; } - - /** Fetch the RGB value for Fills Colour */ - public int getFillsColourRGB() { return fillsColourRGB; } - /** Set the RGB value for Fills Colour */ - public void setFillsColourRGB(int rgb) { fillsColourRGB = rgb; } - - /** Fetch the RGB value for Accent Colour */ - public int getAccentColourRGB() { return accentColourRGB; } - /** Set the RGB value for Accent Colour */ - public void setAccentColourRGB(int rgb) { accentColourRGB = rgb; } - - /** Fetch the RGB value for Accent And Hyperlink Colour */ - public int getAccentAndHyperlinkColourRGB() - { return accentAndHyperlinkColourRGB; } - /** Set the RGB value for Accent And Hyperlink Colour */ - public void setAccentAndHyperlinkColourRGB(int rgb) - { accentAndHyperlinkColourRGB = rgb; } - - /** Fetch the RGB value for Accent And Following Hyperlink Colour */ - public int getAccentAndFollowingHyperlinkColourRGB() - { return accentAndFollowingHyperlinkColourRGB; } - /** Set the RGB value for Accent And Following Hyperlink Colour */ - public void setAccentAndFollowingHyperlinkColourRGB(int rgb) - { accentAndFollowingHyperlinkColourRGB = rgb; } - - /* *************** record code follows ********************** */ - - /** - * For the Colour Scheme (ColorSchem) Atom - */ - protected ColorSchemeAtom(byte[] source, int start, int len) { - // Sanity Checking - we're always 40 bytes long - if (len < 40) { - if(source.length - start < 40) { - throw new HSLFException("Not enough data to form a ColorSchemeAtom (always 40 bytes long) - found " + (source.length - start)); - } - } - - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Grab the rgb values - backgroundColourRGB = LittleEndian.getInt(source, start+8); - textAndLinesColourRGB = LittleEndian.getInt(source,start+8+4); - shadowsColourRGB = LittleEndian.getInt(source,start+8+8); - titleTextColourRGB = LittleEndian.getInt(source,start+8+12); - fillsColourRGB = LittleEndian.getInt(source,start+8+16); - accentColourRGB = LittleEndian.getInt(source,start+8+20); - accentAndHyperlinkColourRGB = LittleEndian.getInt(source,start+8+24); - accentAndFollowingHyperlinkColourRGB = LittleEndian.getInt(source,start+8+28); - } - - /** - * Create a new ColorSchemeAtom, to go with a new Slide - */ - public ColorSchemeAtom(){ - _header = new byte[8]; - LittleEndian.putUShort(_header, 0, 16); - LittleEndian.putUShort(_header, 2, (int)_type); - LittleEndian.putInt(_header, 4, 32); - - // Setup the default rgb values - backgroundColourRGB = 16777215; - textAndLinesColourRGB = 0; - shadowsColourRGB = 8421504; - titleTextColourRGB = 0; - fillsColourRGB = 10079232; - accentColourRGB = 13382451; - accentAndHyperlinkColourRGB = 16764108; - accentAndFollowingHyperlinkColourRGB = 11711154; - } - - - /** - * We are of type 3999 - */ - @Override + private static final long _type = 2032L; + + private final byte[] _header; + private int backgroundColourRGB; + private int textAndLinesColourRGB; + private int shadowsColourRGB; + private int titleTextColourRGB; + private int fillsColourRGB; + private int accentColourRGB; + private int accentAndHyperlinkColourRGB; + private int accentAndFollowingHyperlinkColourRGB; + + /** Fetch the RGB value for Background Colour */ + public int getBackgroundColourRGB() { return backgroundColourRGB; } + /** Set the RGB value for Background Colour */ + public void setBackgroundColourRGB(int rgb) { backgroundColourRGB = rgb; } + + /** Fetch the RGB value for Text And Lines Colour */ + public int getTextAndLinesColourRGB() { return textAndLinesColourRGB; } + /** Set the RGB value for Text And Lines Colour */ + public void setTextAndLinesColourRGB(int rgb) { textAndLinesColourRGB = rgb; } + + /** Fetch the RGB value for Shadows Colour */ + public int getShadowsColourRGB() { return shadowsColourRGB; } + /** Set the RGB value for Shadows Colour */ + public void setShadowsColourRGB(int rgb) { shadowsColourRGB = rgb; } + + /** Fetch the RGB value for Title Text Colour */ + public int getTitleTextColourRGB() { return titleTextColourRGB; } + /** Set the RGB value for Title Text Colour */ + public void setTitleTextColourRGB(int rgb) { titleTextColourRGB = rgb; } + + /** Fetch the RGB value for Fills Colour */ + public int getFillsColourRGB() { return fillsColourRGB; } + /** Set the RGB value for Fills Colour */ + public void setFillsColourRGB(int rgb) { fillsColourRGB = rgb; } + + /** Fetch the RGB value for Accent Colour */ + public int getAccentColourRGB() { return accentColourRGB; } + /** Set the RGB value for Accent Colour */ + public void setAccentColourRGB(int rgb) { accentColourRGB = rgb; } + + /** Fetch the RGB value for Accent And Hyperlink Colour */ + public int getAccentAndHyperlinkColourRGB() + { return accentAndHyperlinkColourRGB; } + /** Set the RGB value for Accent And Hyperlink Colour */ + public void setAccentAndHyperlinkColourRGB(int rgb) + { accentAndHyperlinkColourRGB = rgb; } + + /** Fetch the RGB value for Accent And Following Hyperlink Colour */ + public int getAccentAndFollowingHyperlinkColourRGB() + { return accentAndFollowingHyperlinkColourRGB; } + /** Set the RGB value for Accent And Following Hyperlink Colour */ + public void setAccentAndFollowingHyperlinkColourRGB(int rgb) + { accentAndFollowingHyperlinkColourRGB = rgb; } + + /* *************** record code follows ********************** */ + + /** + * For the Colour Scheme (ColorSchem) Atom + */ + protected ColorSchemeAtom(byte[] source, int start, int len) { + // Sanity Checking - we're always 40 bytes long + if (len < 40) { + if(source.length - start < 40) { + throw new HSLFException("Not enough data to form a ColorSchemeAtom (always 40 bytes long) - found " + (source.length - start)); + } + } + + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Grab the rgb values + backgroundColourRGB = LittleEndian.getInt(source, start+8); + textAndLinesColourRGB = LittleEndian.getInt(source,start+8+4); + shadowsColourRGB = LittleEndian.getInt(source,start+8+8); + titleTextColourRGB = LittleEndian.getInt(source,start+8+12); + fillsColourRGB = LittleEndian.getInt(source,start+8+16); + accentColourRGB = LittleEndian.getInt(source,start+8+20); + accentAndHyperlinkColourRGB = LittleEndian.getInt(source,start+8+24); + accentAndFollowingHyperlinkColourRGB = LittleEndian.getInt(source,start+8+28); + } + + /** + * Create a new ColorSchemeAtom, to go with a new Slide + */ + public ColorSchemeAtom(){ + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 16); + LittleEndian.putUShort(_header, 2, (int)_type); + LittleEndian.putInt(_header, 4, 32); + + // Setup the default rgb values + backgroundColourRGB = 16777215; + textAndLinesColourRGB = 0; + shadowsColourRGB = 8421504; + titleTextColourRGB = 0; + fillsColourRGB = 10079232; + accentColourRGB = 13382451; + accentAndHyperlinkColourRGB = 16764108; + accentAndFollowingHyperlinkColourRGB = 11711154; + } + + + /** + * We are of type 3999 + */ + @Override public long getRecordType() { return _type; } - /** - * Convert from an integer RGB value to individual R, G, B 0-255 values - */ - public static byte[] splitRGB(int rgb) { - byte[] ret = new byte[3]; - - // Serialise to bytes, then grab the right ones out - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - try { - writeLittleEndian(rgb,baos); - } catch(IOException ie) { - // Should never happen - throw new HSLFException(ie); - } - byte[] b = baos.toByteArray(); - System.arraycopy(b,0,ret,0,3); - - return ret; - } - - /** - * Convert from split R, G, B values to an integer RGB value - */ - public static int joinRGB(byte r, byte g, byte b) { - return joinRGB(new byte[] { r,g,b }); - } - /** - * Convert from split R, G, B values to an integer RGB value - */ - public static int joinRGB(byte[] rgb) { - if(rgb.length != 3) { - throw new HSLFException("joinRGB accepts a byte array of 3 values, but got one of " + rgb.length + " values!"); - } - byte[] with_zero = new byte[4]; - System.arraycopy(rgb,0,with_zero,0,3); - with_zero[3] = 0; + /** + * Convert from an integer RGB value to individual R, G, B 0-255 values + */ + public static byte[] splitRGB(int rgb) { + byte[] ret = new byte[3]; + + // Serialise to bytes, then grab the right ones out + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + try { + writeLittleEndian(rgb,baos); + } catch(IOException ie) { + // Should never happen + throw new HSLFException(ie); + } + byte[] b = baos.toByteArray(); + System.arraycopy(b,0,ret,0,3); + + return ret; + } + + /** + * Convert from split R, G, B values to an integer RGB value + */ + public static int joinRGB(byte r, byte g, byte b) { + return joinRGB(new byte[] { r,g,b }); + } + /** + * Convert from split R, G, B values to an integer RGB value + */ + public static int joinRGB(byte[] rgb) { + if(rgb.length != 3) { + throw new HSLFException("joinRGB accepts a byte array of 3 values, but got one of " + rgb.length + " values!"); + } + byte[] with_zero = new byte[4]; + System.arraycopy(rgb,0,with_zero,0,3); + with_zero[3] = 0; return LittleEndian.getInt(with_zero,0); - } + } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - // Header - size or type unchanged - out.write(_header); - - // Write out the rgb values - writeLittleEndian(backgroundColourRGB,out); - writeLittleEndian(textAndLinesColourRGB,out); - writeLittleEndian(shadowsColourRGB,out); - writeLittleEndian(titleTextColourRGB,out); - writeLittleEndian(fillsColourRGB,out); - writeLittleEndian(accentColourRGB,out); - writeLittleEndian(accentAndHyperlinkColourRGB,out); - writeLittleEndian(accentAndFollowingHyperlinkColourRGB,out); - } - - /** - * Returns color by its index - * - * @param idx 0-based color index - * @return color by its index - */ - public int getColor(int idx){ - int[] clr = {backgroundColourRGB, textAndLinesColourRGB, shadowsColourRGB, titleTextColourRGB, - fillsColourRGB, accentColourRGB, accentAndHyperlinkColourRGB, accentAndFollowingHyperlinkColourRGB}; - return clr[idx]; - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - final Map<String, Supplier<?>> m = new LinkedHashMap<>(); - m.put("backgroundColourRGB", this::getBackgroundColourRGB); - m.put("textAndLinesColourRGB", this::getTextAndLinesColourRGB); - m.put("shadowsColourRGB", this::getShadowsColourRGB); - m.put("titleTextColourRGB", this::getTitleTextColourRGB); - m.put("fillsColourRGB", this::getFillsColourRGB); - m.put("accentColourRGB", this::getAccentColourRGB); - m.put("accentAndHyperlinkColourRGB", this::getAccentAndHyperlinkColourRGB); - m.put("accentAndFollowingHyperlinkColourRGB", this::getAccentAndFollowingHyperlinkColourRGB); - return Collections.unmodifiableMap(m); - } + // Header - size or type unchanged + out.write(_header); + + // Write out the rgb values + writeLittleEndian(backgroundColourRGB,out); + writeLittleEndian(textAndLinesColourRGB,out); + writeLittleEndian(shadowsColourRGB,out); + writeLittleEndian(titleTextColourRGB,out); + writeLittleEndian(fillsColourRGB,out); + writeLittleEndian(accentColourRGB,out); + writeLittleEndian(accentAndHyperlinkColourRGB,out); + writeLittleEndian(accentAndFollowingHyperlinkColourRGB,out); + } + + /** + * Returns color by its index + * + * @param idx 0-based color index + * @return color by its index + */ + public int getColor(int idx){ + int[] clr = {backgroundColourRGB, textAndLinesColourRGB, shadowsColourRGB, titleTextColourRGB, + fillsColourRGB, accentColourRGB, accentAndHyperlinkColourRGB, accentAndFollowingHyperlinkColourRGB}; + return clr[idx]; + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + final Map<String, Supplier<?>> m = new LinkedHashMap<>(); + m.put("backgroundColourRGB", this::getBackgroundColourRGB); + m.put("textAndLinesColourRGB", this::getTextAndLinesColourRGB); + m.put("shadowsColourRGB", this::getShadowsColourRGB); + m.put("titleTextColourRGB", this::getTitleTextColourRGB); + m.put("fillsColourRGB", this::getFillsColourRGB); + m.put("accentColourRGB", this::getAccentColourRGB); + m.put("accentAndHyperlinkColourRGB", this::getAccentAndHyperlinkColourRGB); + m.put("accentAndFollowingHyperlinkColourRGB", this::getAccentAndFollowingHyperlinkColourRGB); + return Collections.unmodifiableMap(m); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Comment2000.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Comment2000.java index f0f33ab863..5a54cbfb53 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Comment2000.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Comment2000.java @@ -30,10 +30,10 @@ import static org.apache.logging.log4j.util.Unbox.box; * PPT 2000/XP/etc. (PPT 97 uses plain Escher Text Boxes for comments) */ public final class Comment2000 extends RecordContainer { - private byte[] _header; - private static final long _type = RecordTypes.Comment2000.typeID; + private byte[] _header; + private static final long _type = RecordTypes.Comment2000.typeID; - // Links to our more interesting children + // Links to our more interesting children /** * An optional string that specifies the name of the author of the presentation comment. @@ -53,68 +53,68 @@ public final class Comment2000 extends RecordContainer { */ private Comment2000Atom commentAtom; - /** - * Returns the Comment2000Atom of this Comment - */ - public Comment2000Atom getComment2000Atom() { return commentAtom; } - - /** - * Get the Author of this comment - */ - public String getAuthor() { - return authorRecord == null ? null : authorRecord.getText(); - } - /** - * Set the Author of this comment - */ - public void setAuthor(String author) { - authorRecord.setText(author); - } - - /** - * Get the Author's Initials of this comment - */ - public String getAuthorInitials() { - return authorInitialsRecord == null ? null : authorInitialsRecord.getText(); - } - /** - * Set the Author's Initials of this comment - */ - public void setAuthorInitials(String initials) { - authorInitialsRecord.setText(initials); - } - - /** - * Get the text of this comment - */ - public String getText() { - return commentRecord == null ? null : commentRecord.getText(); - } - /** - * Set the text of this comment - */ - public void setText(String text) { - commentRecord.setText(text); - } - - /** - * Set things up, and find our more interesting children - */ - protected Comment2000(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = org.apache.poi.hslf.record.Record.findChildRecords(source,start+8,len-8); - findInterestingChildren(); - } - - /** - * Go through our child records, picking out the ones that are - * interesting, and saving those for use by the easy helper - * methods. - */ - private void findInterestingChildren() { + /** + * Returns the Comment2000Atom of this Comment + */ + public Comment2000Atom getComment2000Atom() { return commentAtom; } + + /** + * Get the Author of this comment + */ + public String getAuthor() { + return authorRecord == null ? null : authorRecord.getText(); + } + /** + * Set the Author of this comment + */ + public void setAuthor(String author) { + authorRecord.setText(author); + } + + /** + * Get the Author's Initials of this comment + */ + public String getAuthorInitials() { + return authorInitialsRecord == null ? null : authorInitialsRecord.getText(); + } + /** + * Set the Author's Initials of this comment + */ + public void setAuthorInitials(String initials) { + authorInitialsRecord.setText(initials); + } + + /** + * Get the text of this comment + */ + public String getText() { + return commentRecord == null ? null : commentRecord.getText(); + } + /** + * Set the text of this comment + */ + public void setText(String text) { + commentRecord.setText(text); + } + + /** + * Set things up, and find our more interesting children + */ + protected Comment2000(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = org.apache.poi.hslf.record.Record.findChildRecords(source,start+8,len-8); + findInterestingChildren(); + } + + /** + * Go through our child records, picking out the ones that are + * interesting, and saving those for use by the easy helper + * methods. + */ + private void findInterestingChildren() { for(org.apache.poi.hslf.record.Record r : _children){ if (r instanceof CString){ @@ -129,47 +129,47 @@ public final class Comment2000 extends RecordContainer { } else if (r instanceof Comment2000Atom){ commentAtom = (Comment2000Atom)r; } else { - LOG.atWarn().log("Unexpected record with type={} in Comment2000: {}", box(r.getRecordType()),r.getClass().getName()); + LOG.atWarn().log("Unexpected record with type={} in Comment2000: {}", box(r.getRecordType()),r.getClass().getName()); } } - } - - /** - * Create a new Comment2000, with blank fields - */ - public Comment2000() { - _header = new byte[8]; - _children = new org.apache.poi.hslf.record.Record[4]; - - // Setup our header block - _header[0] = 0x0f; // We are a container record - LittleEndian.putShort(_header, 2, (short)_type); - - // Setup our child records - CString csa = new CString(); - CString csb = new CString(); - CString csc = new CString(); - csa.setOptions(0x00); - csb.setOptions(0x10); - csc.setOptions(0x20); - _children[0] = csa; - _children[1] = csb; - _children[2] = csc; - _children[3] = new Comment2000Atom(); - findInterestingChildren(); - } - - /** - * We are of type 1200 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + } + + /** + * Create a new Comment2000, with blank fields + */ + public Comment2000() { + _header = new byte[8]; + _children = new org.apache.poi.hslf.record.Record[4]; + + // Setup our header block + _header[0] = 0x0f; // We are a container record + LittleEndian.putShort(_header, 2, (short)_type); + + // Setup our child records + CString csa = new CString(); + CString csb = new CString(); + CString csc = new CString(); + csa.setOptions(0x00); + csb.setOptions(0x10); + csc.setOptions(0x20); + _children[0] = csa; + _children[1] = csb; + _children[2] = csc; + _children[3] = new Comment2000Atom(); + findInterestingChildren(); + } + + /** + * We are of type 1200 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Comment2000Atom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Comment2000Atom.java index 765b7d41b1..07b9457b5f 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Comment2000Atom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Comment2000Atom.java @@ -98,7 +98,7 @@ public final class Comment2000Atom extends RecordAtom * @return the comment date. */ public Date getDate() { - return SystemTimeUtils.getDate(_data,4); + return SystemTimeUtils.getDate(_data,4); } /** @@ -106,7 +106,7 @@ public final class Comment2000Atom extends RecordAtom * @param date the comment date. */ public void setDate(Date date) { - SystemTimeUtils.storeDate(date, _data, 4); + SystemTimeUtils.storeDate(date, _data, 4); } /** diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/CurrentUserAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/CurrentUserAtom.java index e9e16b91ed..7a2e413dff 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/CurrentUserAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/CurrentUserAtom.java @@ -46,232 +46,232 @@ import org.apache.poi.util.StringUtil; */ public class CurrentUserAtom { - private static final Logger LOG = LogManager.getLogger(CurrentUserAtom.class); - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; - - /** Standard Atom header */ - private static final byte[] atomHeader = new byte[] { 0, 0, -10, 15 }; - /** The PowerPoint magic number for a non-encrypted file */ - private static final byte[] headerToken = new byte[] { 95, -64, -111, -29 }; - /** The PowerPoint magic number for an encrypted file */ - private static final byte[] encHeaderToken = new byte[] { -33, -60, -47, -13 }; - // The Powerpoint 97 version, major and minor numbers - // byte[] ppt97FileVer = new byte[] { 8, 00, -13, 03, 03, 00 }; - - /** The version, major and minor numbers */ - private int docFinalVersion; - private byte docMajorNo; - private byte docMinorNo; - - /** The Offset into the file for the current edit */ + private static final Logger LOG = LogManager.getLogger(CurrentUserAtom.class); + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + + /** Standard Atom header */ + private static final byte[] atomHeader = new byte[] { 0, 0, -10, 15 }; + /** The PowerPoint magic number for a non-encrypted file */ + private static final byte[] headerToken = new byte[] { 95, -64, -111, -29 }; + /** The PowerPoint magic number for an encrypted file */ + private static final byte[] encHeaderToken = new byte[] { -33, -60, -47, -13 }; + // The Powerpoint 97 version, major and minor numbers + // byte[] ppt97FileVer = new byte[] { 8, 00, -13, 03, 03, 00 }; + + /** The version, major and minor numbers */ + private int docFinalVersion; + private byte docMajorNo; + private byte docMinorNo; + + /** The Offset into the file for the current edit */ private long currentEditOffset; - /** The Username of the last person to edit the file */ - private String lastEditUser; - /** The document release version. Almost always 8 */ - private long releaseVersion; - - /** Only correct after reading in or writing out */ - private byte[] _contents; - - /** Flag for encryption state of the whole file */ - private boolean isEncrypted; - - - /* ********************* getter/setter follows *********************** */ - - public int getDocFinalVersion() { return docFinalVersion; } - public byte getDocMajorNo() { return docMajorNo; } - public byte getDocMinorNo() { return docMinorNo; } - - public long getReleaseVersion() { return releaseVersion; } - public void setReleaseVersion(long rv) { releaseVersion = rv; } - - /** Points to the UserEditAtom */ - public long getCurrentEditOffset() { return currentEditOffset; } - public void setCurrentEditOffset(long id ) { currentEditOffset = id; } - - public String getLastEditUsername() { return lastEditUser; } - public void setLastEditUsername(String u) { lastEditUser = u; } - - public boolean isEncrypted() { return isEncrypted; } - public void setEncrypted(boolean isEncrypted) { this.isEncrypted = isEncrypted; } - - - /* ********************* real code follows *************************** */ - - /** - * Create a new Current User Atom - */ - public CurrentUserAtom() { - _contents = new byte[0]; - - // Initialise to empty - docFinalVersion = 0x03f4; - docMajorNo = 3; - docMinorNo = 0; - releaseVersion = 8; - currentEditOffset = 0; - lastEditUser = "Apache POI"; - isEncrypted = false; - } - - - /** - * Find the Current User in the filesystem, and create from that - */ - public CurrentUserAtom(DirectoryNode dir) throws IOException { - // Decide how big it is - DocumentEntry docProps = - (DocumentEntry)dir.getEntry("Current User"); - - // If it's clearly junk, bail out - if(docProps.getSize() > 131072) { - throw new CorruptPowerPointFileException("The Current User stream is implausably long. It's normally 28-200 bytes long, but was " + docProps.getSize() + " bytes"); - } - - // Grab the contents - try (InputStream in = dir.createDocumentInputStream("Current User")) { - _contents = IOUtils.toByteArray(in, docProps.getSize(), MAX_RECORD_LENGTH); - } - - // See how long it is. If it's under 28 bytes long, we can't - // read it - if(_contents.length < 28) { - boolean isPP95 = dir.hasEntry(PP95_DOCUMENT); - // PPT95 has 4 byte size, then data - if (!isPP95 && _contents.length >= 4) { - int size = LittleEndian.getInt(_contents); - isPP95 = (size + 4 == _contents.length); - } - - if (isPP95) { - throw new OldPowerPointFormatException("Based on the Current User stream, you seem to have supplied a PowerPoint95 file, which isn't supported"); - } else { - throw new CorruptPowerPointFileException("The Current User stream must be at least 28 bytes long, but was only " + _contents.length); - } - } - - // Set everything up - init(); - } - - /** - * Actually do the creation from a block of bytes - */ - private void init() { - // First up is the size, in 4 bytes, which is fixed - // Then is the header - - isEncrypted = (LittleEndian.getInt(encHeaderToken) == LittleEndian.getInt(_contents,12)); - - // Grab the edit offset - currentEditOffset = LittleEndian.getUInt(_contents,16); - - // Grab the versions - docFinalVersion = LittleEndian.getUShort(_contents,22); - docMajorNo = _contents[24]; - docMinorNo = _contents[25]; - - // Get the username length - long usernameLen = LittleEndian.getUShort(_contents,20); - if(usernameLen > 512) { - // Handle the case of it being garbage - LOG.atWarn().log("Invalid username length {} found, treating as if there was no username set", box(usernameLen)); - usernameLen = 0; - } - - // Now we know the length of the username, - // use this to grab the revision - if(_contents.length >= 28+(int)usernameLen + 4) { - releaseVersion = LittleEndian.getUInt(_contents,28+(int)usernameLen); - } else { - // No revision given, as not enough data. Odd - releaseVersion = 0; - } - - // Grab the unicode username, if stored - int start = 28+(int)usernameLen+4; - - if(_contents.length >= start+2*usernameLen) { - lastEditUser = StringUtil.getFromUnicodeLE(_contents, start, (int)usernameLen); - } else { - // Fake from the 8 bit version - lastEditUser = StringUtil.getFromCompressedUnicode(_contents, 28, (int)usernameLen); - } - } - - - /** - * Writes ourselves back out - */ - public void writeOut(OutputStream out) throws IOException { - // Decide on the size - // 8 = atom header - // 20 = up to name - // 4 = revision - // 3 * len = ascii + unicode - int size = 8 + 20 + 4 + (3 * lastEditUser.length()); - _contents = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); - - // First we have a 8 byte atom header - System.arraycopy(atomHeader,0,_contents,0,4); - // Size is 20+user len + revision len(4) - int atomSize = 20+4+lastEditUser.length(); - LittleEndian.putInt(_contents,4,atomSize); - - // Now we have the size of the details, which is 20 - LittleEndian.putInt(_contents,8,20); - - // Now the ppt un-encrypted header token (4 bytes) - System.arraycopy((isEncrypted ? encHeaderToken : headerToken),0,_contents,12,4); - - // Now the current edit offset - LittleEndian.putInt(_contents,16,(int)currentEditOffset); - - // The username gets stored twice, once as US - // ascii, and again as unicode laster on - byte[] asciiUN = IOUtils.safelyAllocate(lastEditUser.length(), MAX_RECORD_LENGTH); - StringUtil.putCompressedUnicode(lastEditUser,asciiUN,0); - - // Now we're able to do the length of the last edited user - LittleEndian.putShort(_contents,20,(short)asciiUN.length); - - // Now the file versions, 2+1+1 - LittleEndian.putShort(_contents,22,(short)docFinalVersion); - _contents[24] = docMajorNo; - _contents[25] = docMinorNo; - - // 2 bytes blank - _contents[26] = 0; - _contents[27] = 0; - - // At this point we have the username as us ascii - System.arraycopy(asciiUN,0,_contents,28,asciiUN.length); - - // 4 byte release version - LittleEndian.putInt(_contents,28+asciiUN.length,(int)releaseVersion); - - // username in unicode - byte [] ucUN = IOUtils.safelyAllocate(lastEditUser.length() * 2L, MAX_RECORD_LENGTH); - StringUtil.putUnicodeLE(lastEditUser,ucUN,0); - System.arraycopy(ucUN,0,_contents,28+asciiUN.length+4,ucUN.length); - - // Write out - out.write(_contents); - } - - /** - * Writes ourselves back out to a filesystem - */ - public void writeToFS(POIFSFileSystem fs) throws IOException { - // Grab contents - try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) { - writeOut(baos); - try (InputStream is = baos.toInputStream()) { - // Write out - fs.createOrUpdateDocument(is, "Current User"); - } - } - } + /** The Username of the last person to edit the file */ + private String lastEditUser; + /** The document release version. Almost always 8 */ + private long releaseVersion; + + /** Only correct after reading in or writing out */ + private byte[] _contents; + + /** Flag for encryption state of the whole file */ + private boolean isEncrypted; + + + /* ********************* getter/setter follows *********************** */ + + public int getDocFinalVersion() { return docFinalVersion; } + public byte getDocMajorNo() { return docMajorNo; } + public byte getDocMinorNo() { return docMinorNo; } + + public long getReleaseVersion() { return releaseVersion; } + public void setReleaseVersion(long rv) { releaseVersion = rv; } + + /** Points to the UserEditAtom */ + public long getCurrentEditOffset() { return currentEditOffset; } + public void setCurrentEditOffset(long id ) { currentEditOffset = id; } + + public String getLastEditUsername() { return lastEditUser; } + public void setLastEditUsername(String u) { lastEditUser = u; } + + public boolean isEncrypted() { return isEncrypted; } + public void setEncrypted(boolean isEncrypted) { this.isEncrypted = isEncrypted; } + + + /* ********************* real code follows *************************** */ + + /** + * Create a new Current User Atom + */ + public CurrentUserAtom() { + _contents = new byte[0]; + + // Initialise to empty + docFinalVersion = 0x03f4; + docMajorNo = 3; + docMinorNo = 0; + releaseVersion = 8; + currentEditOffset = 0; + lastEditUser = "Apache POI"; + isEncrypted = false; + } + + + /** + * Find the Current User in the filesystem, and create from that + */ + public CurrentUserAtom(DirectoryNode dir) throws IOException { + // Decide how big it is + DocumentEntry docProps = + (DocumentEntry)dir.getEntry("Current User"); + + // If it's clearly junk, bail out + if(docProps.getSize() > 131072) { + throw new CorruptPowerPointFileException("The Current User stream is implausably long. It's normally 28-200 bytes long, but was " + docProps.getSize() + " bytes"); + } + + // Grab the contents + try (InputStream in = dir.createDocumentInputStream("Current User")) { + _contents = IOUtils.toByteArray(in, docProps.getSize(), MAX_RECORD_LENGTH); + } + + // See how long it is. If it's under 28 bytes long, we can't + // read it + if(_contents.length < 28) { + boolean isPP95 = dir.hasEntry(PP95_DOCUMENT); + // PPT95 has 4 byte size, then data + if (!isPP95 && _contents.length >= 4) { + int size = LittleEndian.getInt(_contents); + isPP95 = (size + 4 == _contents.length); + } + + if (isPP95) { + throw new OldPowerPointFormatException("Based on the Current User stream, you seem to have supplied a PowerPoint95 file, which isn't supported"); + } else { + throw new CorruptPowerPointFileException("The Current User stream must be at least 28 bytes long, but was only " + _contents.length); + } + } + + // Set everything up + init(); + } + + /** + * Actually do the creation from a block of bytes + */ + private void init() { + // First up is the size, in 4 bytes, which is fixed + // Then is the header + + isEncrypted = (LittleEndian.getInt(encHeaderToken) == LittleEndian.getInt(_contents,12)); + + // Grab the edit offset + currentEditOffset = LittleEndian.getUInt(_contents,16); + + // Grab the versions + docFinalVersion = LittleEndian.getUShort(_contents,22); + docMajorNo = _contents[24]; + docMinorNo = _contents[25]; + + // Get the username length + long usernameLen = LittleEndian.getUShort(_contents,20); + if(usernameLen > 512) { + // Handle the case of it being garbage + LOG.atWarn().log("Invalid username length {} found, treating as if there was no username set", box(usernameLen)); + usernameLen = 0; + } + + // Now we know the length of the username, + // use this to grab the revision + if(_contents.length >= 28+(int)usernameLen + 4) { + releaseVersion = LittleEndian.getUInt(_contents,28+(int)usernameLen); + } else { + // No revision given, as not enough data. Odd + releaseVersion = 0; + } + + // Grab the unicode username, if stored + int start = 28+(int)usernameLen+4; + + if(_contents.length >= start+2*usernameLen) { + lastEditUser = StringUtil.getFromUnicodeLE(_contents, start, (int)usernameLen); + } else { + // Fake from the 8 bit version + lastEditUser = StringUtil.getFromCompressedUnicode(_contents, 28, (int)usernameLen); + } + } + + + /** + * Writes ourselves back out + */ + public void writeOut(OutputStream out) throws IOException { + // Decide on the size + // 8 = atom header + // 20 = up to name + // 4 = revision + // 3 * len = ascii + unicode + int size = 8 + 20 + 4 + (3 * lastEditUser.length()); + _contents = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); + + // First we have a 8 byte atom header + System.arraycopy(atomHeader,0,_contents,0,4); + // Size is 20+user len + revision len(4) + int atomSize = 20+4+lastEditUser.length(); + LittleEndian.putInt(_contents,4,atomSize); + + // Now we have the size of the details, which is 20 + LittleEndian.putInt(_contents,8,20); + + // Now the ppt un-encrypted header token (4 bytes) + System.arraycopy((isEncrypted ? encHeaderToken : headerToken),0,_contents,12,4); + + // Now the current edit offset + LittleEndian.putInt(_contents,16,(int)currentEditOffset); + + // The username gets stored twice, once as US + // ascii, and again as unicode laster on + byte[] asciiUN = IOUtils.safelyAllocate(lastEditUser.length(), MAX_RECORD_LENGTH); + StringUtil.putCompressedUnicode(lastEditUser,asciiUN,0); + + // Now we're able to do the length of the last edited user + LittleEndian.putShort(_contents,20,(short)asciiUN.length); + + // Now the file versions, 2+1+1 + LittleEndian.putShort(_contents,22,(short)docFinalVersion); + _contents[24] = docMajorNo; + _contents[25] = docMinorNo; + + // 2 bytes blank + _contents[26] = 0; + _contents[27] = 0; + + // At this point we have the username as us ascii + System.arraycopy(asciiUN,0,_contents,28,asciiUN.length); + + // 4 byte release version + LittleEndian.putInt(_contents,28+asciiUN.length,(int)releaseVersion); + + // username in unicode + byte [] ucUN = IOUtils.safelyAllocate(lastEditUser.length() * 2L, MAX_RECORD_LENGTH); + StringUtil.putUnicodeLE(lastEditUser,ucUN,0); + System.arraycopy(ucUN,0,_contents,28+asciiUN.length+4,ucUN.length); + + // Write out + out.write(_contents); + } + + /** + * Writes ourselves back out to a filesystem + */ + public void writeToFS(POIFSFileSystem fs) throws IOException { + // Grab contents + try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) { + writeOut(baos); + try (InputStream is = baos.toInputStream()) { + // Write out + fs.createOrUpdateDocument(is, "Current User"); + } + } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocInfoListContainer.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocInfoListContainer.java index a43e475034..87c8d5d700 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocInfoListContainer.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocInfoListContainer.java @@ -29,62 +29,62 @@ import org.apache.poi.util.LittleEndian; * A container record that specifies information about the document and document display settings. */ public final class DocInfoListContainer extends RecordContainer { - private byte[] _header; - private static final long _type = RecordTypes.List.typeID; - - // Links to our more interesting children - - /** - * Set things up, and find our more interesting children - */ - protected DocInfoListContainer(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source,start,start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - findInterestingChildren(); - } - - /** - * Go through our child records, picking out the ones that are - * interesting, and saving those for use by the easy helper - * methods. - */ - private void findInterestingChildren() { - - } - - /** - * Create a new DocInfoListContainer, with blank fields - not yet supported - */ - private DocInfoListContainer() { - _header = new byte[8]; - _children = new org.apache.poi.hslf.record.Record[0]; - - // Setup our header block - _header[0] = 0x0f; // We are a container record - LittleEndian.putShort(_header, 2, (short)_type); - - // Setup our child records - findInterestingChildren(); - } - - /** - * We are of type 0x7D0 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return null; - } + private byte[] _header; + private static final long _type = RecordTypes.List.typeID; + + // Links to our more interesting children + + /** + * Set things up, and find our more interesting children + */ + protected DocInfoListContainer(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source,start,start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + findInterestingChildren(); + } + + /** + * Go through our child records, picking out the ones that are + * interesting, and saving those for use by the easy helper + * methods. + */ + private void findInterestingChildren() { + + } + + /** + * Create a new DocInfoListContainer, with blank fields - not yet supported + */ + private DocInfoListContainer() { + _header = new byte[8]; + _children = new org.apache.poi.hslf.record.Record[0]; + + // Setup our header block + _header[0] = 0x0f; // We are a container record + LittleEndian.putShort(_header, 2, (short)_type); + + // Setup our child records + findInterestingChildren(); + } + + /** + * We are of type 0x7D0 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return null; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Document.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Document.java index de69dd05a5..e7c993ef38 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Document.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Document.java @@ -31,177 +31,177 @@ import static org.apache.logging.log4j.util.Unbox.box; public final class Document extends PositionDependentRecordContainer { - private byte[] _header; - private static long _type = 1000; - - // Links to our more interesting children - private DocumentAtom documentAtom; - private Environment environment; - private PPDrawingGroup ppDrawing; - private SlideListWithText[] slwts; - private ExObjList exObjList; // Can be null - - /** - * Returns the DocumentAtom of this Document - */ - public DocumentAtom getDocumentAtom() { return documentAtom; } - - /** - * Returns the Environment of this Notes, which lots of - * settings for the document in it - */ - public Environment getEnvironment() { return environment; } - - /** - * Returns the PPDrawingGroup, which holds an Escher Structure - * that contains information on pictures in the slides. - */ - public PPDrawingGroup getPPDrawingGroup() { return ppDrawing; } - - /** - * Returns the ExObjList, which holds the references to - * external objects used in the slides. This may be null, if - * there are no external references. - * - * @param create if true, create an ExObjList if it doesn't exist - */ - public ExObjList getExObjList(boolean create) { - if (exObjList == null && create) { - exObjList = new ExObjList(); - addChildAfter(exObjList, getDocumentAtom()); - } - return exObjList; + private byte[] _header; + private static long _type = 1000; + + // Links to our more interesting children + private DocumentAtom documentAtom; + private Environment environment; + private PPDrawingGroup ppDrawing; + private SlideListWithText[] slwts; + private ExObjList exObjList; // Can be null + + /** + * Returns the DocumentAtom of this Document + */ + public DocumentAtom getDocumentAtom() { return documentAtom; } + + /** + * Returns the Environment of this Notes, which lots of + * settings for the document in it + */ + public Environment getEnvironment() { return environment; } + + /** + * Returns the PPDrawingGroup, which holds an Escher Structure + * that contains information on pictures in the slides. + */ + public PPDrawingGroup getPPDrawingGroup() { return ppDrawing; } + + /** + * Returns the ExObjList, which holds the references to + * external objects used in the slides. This may be null, if + * there are no external references. + * + * @param create if true, create an ExObjList if it doesn't exist + */ + public ExObjList getExObjList(boolean create) { + if (exObjList == null && create) { + exObjList = new ExObjList(); + addChildAfter(exObjList, getDocumentAtom()); + } + return exObjList; } - /** - * Returns all the SlideListWithTexts that are defined for - * this Document. They hold the text, and some of the text - * properties, which are referred to by the slides. - * This will normally return an array of size 2 or 3 - */ - public SlideListWithText[] getSlideListWithTexts() { return slwts; } + /** + * Returns all the SlideListWithTexts that are defined for + * this Document. They hold the text, and some of the text + * properties, which are referred to by the slides. + * This will normally return an array of size 2 or 3 + */ + public SlideListWithText[] getSlideListWithTexts() { return slwts; } /** - * Returns the SlideListWithText that deals with the - * Master Slides - */ - public SlideListWithText getMasterSlideListWithText() { - for (SlideListWithText slwt : slwts) { - if (slwt.getInstance() == SlideListWithText.MASTER) { - return slwt; - } - } + * Returns the SlideListWithText that deals with the + * Master Slides + */ + public SlideListWithText getMasterSlideListWithText() { + for (SlideListWithText slwt : slwts) { + if (slwt.getInstance() == SlideListWithText.MASTER) { + return slwt; + } + } return null; } - /** - * Returns the SlideListWithText that deals with the - * Slides, or null if there isn't one - */ - public SlideListWithText getSlideSlideListWithText() { - for (SlideListWithText slwt : slwts) { - if (slwt.getInstance() == SlideListWithText.SLIDES) { - return slwt; - } - } - return null; + /** + * Returns the SlideListWithText that deals with the + * Slides, or null if there isn't one + */ + public SlideListWithText getSlideSlideListWithText() { + for (SlideListWithText slwt : slwts) { + if (slwt.getInstance() == SlideListWithText.SLIDES) { + return slwt; + } + } + return null; } - /** - * Returns the SlideListWithText that deals with the - * notes, or null if there isn't one - */ - public SlideListWithText getNotesSlideListWithText() { - for (SlideListWithText slwt : slwts) { - if (slwt.getInstance() == SlideListWithText.NOTES) { - return slwt; - } - } - return null; + /** + * Returns the SlideListWithText that deals with the + * notes, or null if there isn't one + */ + public SlideListWithText getNotesSlideListWithText() { + for (SlideListWithText slwt : slwts) { + if (slwt.getInstance() == SlideListWithText.NOTES) { + return slwt; + } + } + return null; + } + + + /** + * Set things up, and find our more interesting children + */ + /* package */ Document(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + + // Our first one should be a document atom + if(! (_children[0] instanceof DocumentAtom)) { + throw new IllegalStateException("The first child of a Document must be a DocumentAtom"); + } + documentAtom = (DocumentAtom)_children[0]; + + // Find how many SlideListWithTexts we have + // Also, grab the Environment and PPDrawing records + // on our way past + int slwtcount = 0; + for(int i=1; i<_children.length; i++) { + if(_children[i] instanceof SlideListWithText) { + slwtcount++; + } + if(_children[i] instanceof Environment) { + environment = (Environment)_children[i]; + } + if(_children[i] instanceof PPDrawingGroup) { + ppDrawing = (PPDrawingGroup)_children[i]; + } + if(_children[i] instanceof ExObjList) { + exObjList = (ExObjList)_children[i]; + } + } + + // You should only every have 1, 2 or 3 SLWTs + // (normally it's 2, or 3 if you have notes) + // Complain if it's not + if(slwtcount == 0) { + LOG.atWarn().log("No SlideListWithText's found - there should normally be at least one!"); + } + if(slwtcount > 3) { + LOG.atWarn().log("Found {} SlideListWithTexts - normally there should only be three!", box(slwtcount)); + } + + // Now grab all the SLWTs + slwts = new SlideListWithText[slwtcount]; + slwtcount = 0; + for(int i=1; i<_children.length; i++) { + if(_children[i] instanceof SlideListWithText) { + slwts[slwtcount] = (SlideListWithText)_children[i]; + slwtcount++; + } + } } + /** + * Adds a new SlideListWithText record, at the appropriate + * point in the child records. + */ + public void addSlideListWithText(SlideListWithText slwt) { + // The new SlideListWithText should go in + // just before the EndDocumentRecord + Record endDoc = _children[_children.length - 1]; + if(endDoc.getRecordType() == RecordTypes.RoundTripCustomTableStyles12.typeID) { + // last record can optionally be a RoundTripCustomTableStyles12Atom + endDoc = _children[_children.length - 2]; + } + if(endDoc.getRecordType() != RecordTypes.EndDocument.typeID) { + throw new IllegalStateException("The last child record of a Document should be EndDocument, but it was " + endDoc); + } - /** - * Set things up, and find our more interesting children - */ - /* package */ Document(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - - // Our first one should be a document atom - if(! (_children[0] instanceof DocumentAtom)) { - throw new IllegalStateException("The first child of a Document must be a DocumentAtom"); - } - documentAtom = (DocumentAtom)_children[0]; - - // Find how many SlideListWithTexts we have - // Also, grab the Environment and PPDrawing records - // on our way past - int slwtcount = 0; - for(int i=1; i<_children.length; i++) { - if(_children[i] instanceof SlideListWithText) { - slwtcount++; - } - if(_children[i] instanceof Environment) { - environment = (Environment)_children[i]; - } - if(_children[i] instanceof PPDrawingGroup) { - ppDrawing = (PPDrawingGroup)_children[i]; - } - if(_children[i] instanceof ExObjList) { - exObjList = (ExObjList)_children[i]; - } - } - - // You should only every have 1, 2 or 3 SLWTs - // (normally it's 2, or 3 if you have notes) - // Complain if it's not - if(slwtcount == 0) { - LOG.atWarn().log("No SlideListWithText's found - there should normally be at least one!"); - } - if(slwtcount > 3) { - LOG.atWarn().log("Found {} SlideListWithTexts - normally there should only be three!", box(slwtcount)); - } - - // Now grab all the SLWTs - slwts = new SlideListWithText[slwtcount]; - slwtcount = 0; - for(int i=1; i<_children.length; i++) { - if(_children[i] instanceof SlideListWithText) { - slwts[slwtcount] = (SlideListWithText)_children[i]; - slwtcount++; - } - } - } - - /** - * Adds a new SlideListWithText record, at the appropriate - * point in the child records. - */ - public void addSlideListWithText(SlideListWithText slwt) { - // The new SlideListWithText should go in - // just before the EndDocumentRecord - Record endDoc = _children[_children.length - 1]; - if(endDoc.getRecordType() == RecordTypes.RoundTripCustomTableStyles12.typeID) { - // last record can optionally be a RoundTripCustomTableStyles12Atom - endDoc = _children[_children.length - 2]; - } - if(endDoc.getRecordType() != RecordTypes.EndDocument.typeID) { - throw new IllegalStateException("The last child record of a Document should be EndDocument, but it was " + endDoc); - } - - // Add in the record - addChildBefore(slwt, endDoc); - - // Updated our cached list of SlideListWithText records - int newSize = slwts.length + 1; - SlideListWithText[] nl = new SlideListWithText[newSize]; - System.arraycopy(slwts, 0, nl, 0, slwts.length); - nl[nl.length-1] = slwt; - slwts = nl; - } + // Add in the record + addChildBefore(slwt, endDoc); + + // Updated our cached list of SlideListWithText records + int newSize = slwts.length + 1; + SlideListWithText[] nl = new SlideListWithText[newSize]; + System.arraycopy(slwts, 0, nl, 0, slwts.length); + nl[nl.length-1] = slwt; + slwts = nl; + } public void removeSlideListWithText(SlideListWithText slwt) { ArrayList<SlideListWithText> lst = new ArrayList<>(); @@ -214,16 +214,16 @@ public final class Document extends PositionDependentRecordContainer slwts = lst.toArray(new SlideListWithText[0]); } - /** - * We are of type 1000 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + /** + * We are of type 1000 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocumentAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocumentAtom.java index 4764c91d21..4388aa0704 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocumentAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocumentAtom.java @@ -36,224 +36,224 @@ import org.apache.poi.util.Removal; @SuppressWarnings({"WeakerAccess", "unused"}) public final class DocumentAtom extends RecordAtom { - /** - * Holds the different Slide Size values - */ - public enum SlideSize { - /** Slide size ratio is consistent with a computer screen. */ - ON_SCREEN, - /** Slide size ratio is consistent with letter paper. */ - LETTER_SIZED_PAPER, - /** Slide size ratio is consistent with A4 paper. */ - A4_SIZED_PAPER, - /** Slide size ratio is consistent with 35mm photo slides. */ - ON_35MM, - /** Slide size ratio is consistent with overhead projector slides. */ - OVERHEAD, - /** Slide size ratio is consistent with a banner. */ - BANNER, - /** - * Slide size ratio that is not consistent with any of the other specified slide sizes in - * this enumeration. - */ - CUSTOM - } - - - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; - - - - private final byte[] _header = new byte[8]; - private static final long _type = RecordTypes.DocumentAtom.typeID; - - private long slideSizeX; // PointAtom, assume 1st 4 bytes = X - private long slideSizeY; // PointAtom, assume 2nd 4 bytes = Y - private long notesSizeX; // PointAtom, assume 1st 4 bytes = X - private long notesSizeY; // PointAtom, assume 2nd 4 bytes = Y - private long serverZoomFrom; // RatioAtom, assume 1st 4 bytes = from - private long serverZoomTo; // RatioAtom, assume 2nd 4 bytes = to - - private final long notesMasterPersist; // ref to NotesMaster, 0 if none - private final long handoutMasterPersist; // ref to HandoutMaster, 0 if none - - private final int firstSlideNum; - private int slideSizeType; // see DocumentAtom.SlideSize - - private byte saveWithFonts; - private final byte omitTitlePlace; - private final byte rightToLeft; - private final byte showComments; - - private final byte[] reserved; - - - public long getSlideSizeX() { return slideSizeX; } - public long getSlideSizeY() { return slideSizeY; } - public long getNotesSizeX() { return notesSizeX; } - public long getNotesSizeY() { return notesSizeY; } - public void setSlideSizeX(long x) { slideSizeX = x; } - public void setSlideSizeY(long y) { slideSizeY = y; } - public void setNotesSizeX(long x) { notesSizeX = x; } - public void setNotesSizeY(long y) { notesSizeY = y; } - - public long getServerZoomFrom() { return serverZoomFrom; } - public long getServerZoomTo() { return serverZoomTo; } - public void setServerZoomFrom(long zoom) { serverZoomFrom = zoom; } - public void setServerZoomTo(long zoom) { serverZoomTo = zoom; } - - /** Returns a reference to the NotesMaster, or 0 if none */ - public long getNotesMasterPersist() { return notesMasterPersist; } - /** Returns a reference to the HandoutMaster, or 0 if none */ - public long getHandoutMasterPersist() { return handoutMasterPersist; } - - public int getFirstSlideNum() { return firstSlideNum; } - - /** - * The Size of the Document's slides, @see DocumentAtom.SlideSize for values - * @deprecated to be replaced by enum - */ - @Deprecated - @Removal(version = "5.0.0") - public int getSlideSizeType() { return slideSizeType; } - - public SlideSize getSlideSizeTypeEnum() { - return SlideSize.values()[slideSizeType]; - } - - public void setSlideSize(SlideSize size) { - slideSizeType = size.ordinal(); - } - - /** Was the document saved with True Type fonts embeded? */ - public boolean getSaveWithFonts() { - return saveWithFonts != 0; - } - - /** Set the font embedding state */ - public void setSaveWithFonts(boolean saveWithFonts) { - this.saveWithFonts = (byte)(saveWithFonts ? 1 : 0); - } - - /** Have the placeholders on the title slide been omitted? */ - public boolean getOmitTitlePlace() { - return omitTitlePlace != 0; - } - - /** Is this a Bi-Directional PPT Doc? */ - public boolean getRightToLeft() { - return rightToLeft != 0; - } - - /** Are comment shapes visible? */ - public boolean getShowComments() { - return showComments != 0; - } - - - /* *************** record code follows ********************** */ - - /** - * For the Document Atom - */ - /* package */ DocumentAtom(byte[] source, int start, int len) { - final int maxLen = Math.max(len, 48); - LittleEndianByteArrayInputStream leis = - new LittleEndianByteArrayInputStream(source, start, maxLen); - - // Get the header - leis.readFully(_header); - - // Get the sizes and zoom ratios - slideSizeX = leis.readInt(); - slideSizeY = leis.readInt(); - notesSizeX = leis.readInt(); - notesSizeY = leis.readInt(); - serverZoomFrom = leis.readInt(); - serverZoomTo = leis.readInt(); - - // Get the master persists - notesMasterPersist = leis.readInt(); - handoutMasterPersist = leis.readInt(); - - // Get the ID of the first slide - firstSlideNum = leis.readShort(); - - // Get the slide size type - slideSizeType = leis.readShort(); - - // Get the booleans as bytes - saveWithFonts = leis.readByte(); - omitTitlePlace = leis.readByte(); - rightToLeft = leis.readByte(); - showComments = leis.readByte(); - - // If there's any other bits of data, keep them about - reserved = IOUtils.safelyAllocate(maxLen-48L, MAX_RECORD_LENGTH); - leis.readFully(reserved); - } - - /** - * We are of type 1001 - */ - @Override - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override - public void writeOut(OutputStream out) throws IOException { - // Header - out.write(_header); - - // The sizes and zoom ratios - writeLittleEndian((int)slideSizeX,out); - writeLittleEndian((int)slideSizeY,out); - writeLittleEndian((int)notesSizeX,out); - writeLittleEndian((int)notesSizeY,out); - writeLittleEndian((int)serverZoomFrom,out); - writeLittleEndian((int)serverZoomTo,out); - - // The master persists - writeLittleEndian((int)notesMasterPersist,out); - writeLittleEndian((int)handoutMasterPersist,out); - - // The ID of the first slide - writeLittleEndian((short)firstSlideNum,out); - - // The slide size type - writeLittleEndian((short)slideSizeType,out); - - // The booleans as bytes - out.write(saveWithFonts); - out.write(omitTitlePlace); - out.write(rightToLeft); - out.write(showComments); - - // Reserved data - out.write(reserved); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - final Map<String, Supplier<?>> m = new LinkedHashMap<>(); - m.put("slideSizeX", this::getSlideSizeX); - m.put("slideSizeY", this::getSlideSizeY); - m.put("notesSizeX", this::getNotesSizeX); - m.put("notesSizeY", this::getNotesSizeY); - m.put("serverZoomFrom", this::getServerZoomFrom); - m.put("serverZoomTo", this::getServerZoomTo); - m.put("notesMasterPersist", this::getNotesMasterPersist); - m.put("handoutMasterPersist", this::getHandoutMasterPersist); - m.put("firstSlideNum", this::getFirstSlideNum); - m.put("slideSize", this::getSlideSizeTypeEnum); - m.put("saveWithFonts", this::getSaveWithFonts); - m.put("omitTitlePlace", this::getOmitTitlePlace); - m.put("rightToLeft", this::getRightToLeft); - m.put("showComments", this::getShowComments); - return Collections.unmodifiableMap(m); - } + /** + * Holds the different Slide Size values + */ + public enum SlideSize { + /** Slide size ratio is consistent with a computer screen. */ + ON_SCREEN, + /** Slide size ratio is consistent with letter paper. */ + LETTER_SIZED_PAPER, + /** Slide size ratio is consistent with A4 paper. */ + A4_SIZED_PAPER, + /** Slide size ratio is consistent with 35mm photo slides. */ + ON_35MM, + /** Slide size ratio is consistent with overhead projector slides. */ + OVERHEAD, + /** Slide size ratio is consistent with a banner. */ + BANNER, + /** + * Slide size ratio that is not consistent with any of the other specified slide sizes in + * this enumeration. + */ + CUSTOM + } + + + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + + + + private final byte[] _header = new byte[8]; + private static final long _type = RecordTypes.DocumentAtom.typeID; + + private long slideSizeX; // PointAtom, assume 1st 4 bytes = X + private long slideSizeY; // PointAtom, assume 2nd 4 bytes = Y + private long notesSizeX; // PointAtom, assume 1st 4 bytes = X + private long notesSizeY; // PointAtom, assume 2nd 4 bytes = Y + private long serverZoomFrom; // RatioAtom, assume 1st 4 bytes = from + private long serverZoomTo; // RatioAtom, assume 2nd 4 bytes = to + + private final long notesMasterPersist; // ref to NotesMaster, 0 if none + private final long handoutMasterPersist; // ref to HandoutMaster, 0 if none + + private final int firstSlideNum; + private int slideSizeType; // see DocumentAtom.SlideSize + + private byte saveWithFonts; + private final byte omitTitlePlace; + private final byte rightToLeft; + private final byte showComments; + + private final byte[] reserved; + + + public long getSlideSizeX() { return slideSizeX; } + public long getSlideSizeY() { return slideSizeY; } + public long getNotesSizeX() { return notesSizeX; } + public long getNotesSizeY() { return notesSizeY; } + public void setSlideSizeX(long x) { slideSizeX = x; } + public void setSlideSizeY(long y) { slideSizeY = y; } + public void setNotesSizeX(long x) { notesSizeX = x; } + public void setNotesSizeY(long y) { notesSizeY = y; } + + public long getServerZoomFrom() { return serverZoomFrom; } + public long getServerZoomTo() { return serverZoomTo; } + public void setServerZoomFrom(long zoom) { serverZoomFrom = zoom; } + public void setServerZoomTo(long zoom) { serverZoomTo = zoom; } + + /** Returns a reference to the NotesMaster, or 0 if none */ + public long getNotesMasterPersist() { return notesMasterPersist; } + /** Returns a reference to the HandoutMaster, or 0 if none */ + public long getHandoutMasterPersist() { return handoutMasterPersist; } + + public int getFirstSlideNum() { return firstSlideNum; } + + /** + * The Size of the Document's slides, @see DocumentAtom.SlideSize for values + * @deprecated to be replaced by enum + */ + @Deprecated + @Removal(version = "5.0.0") + public int getSlideSizeType() { return slideSizeType; } + + public SlideSize getSlideSizeTypeEnum() { + return SlideSize.values()[slideSizeType]; + } + + public void setSlideSize(SlideSize size) { + slideSizeType = size.ordinal(); + } + + /** Was the document saved with True Type fonts embeded? */ + public boolean getSaveWithFonts() { + return saveWithFonts != 0; + } + + /** Set the font embedding state */ + public void setSaveWithFonts(boolean saveWithFonts) { + this.saveWithFonts = (byte)(saveWithFonts ? 1 : 0); + } + + /** Have the placeholders on the title slide been omitted? */ + public boolean getOmitTitlePlace() { + return omitTitlePlace != 0; + } + + /** Is this a Bi-Directional PPT Doc? */ + public boolean getRightToLeft() { + return rightToLeft != 0; + } + + /** Are comment shapes visible? */ + public boolean getShowComments() { + return showComments != 0; + } + + + /* *************** record code follows ********************** */ + + /** + * For the Document Atom + */ + /* package */ DocumentAtom(byte[] source, int start, int len) { + final int maxLen = Math.max(len, 48); + LittleEndianByteArrayInputStream leis = + new LittleEndianByteArrayInputStream(source, start, maxLen); + + // Get the header + leis.readFully(_header); + + // Get the sizes and zoom ratios + slideSizeX = leis.readInt(); + slideSizeY = leis.readInt(); + notesSizeX = leis.readInt(); + notesSizeY = leis.readInt(); + serverZoomFrom = leis.readInt(); + serverZoomTo = leis.readInt(); + + // Get the master persists + notesMasterPersist = leis.readInt(); + handoutMasterPersist = leis.readInt(); + + // Get the ID of the first slide + firstSlideNum = leis.readShort(); + + // Get the slide size type + slideSizeType = leis.readShort(); + + // Get the booleans as bytes + saveWithFonts = leis.readByte(); + omitTitlePlace = leis.readByte(); + rightToLeft = leis.readByte(); + showComments = leis.readByte(); + + // If there's any other bits of data, keep them about + reserved = IOUtils.safelyAllocate(maxLen-48L, MAX_RECORD_LENGTH); + leis.readFully(reserved); + } + + /** + * We are of type 1001 + */ + @Override + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override + public void writeOut(OutputStream out) throws IOException { + // Header + out.write(_header); + + // The sizes and zoom ratios + writeLittleEndian((int)slideSizeX,out); + writeLittleEndian((int)slideSizeY,out); + writeLittleEndian((int)notesSizeX,out); + writeLittleEndian((int)notesSizeY,out); + writeLittleEndian((int)serverZoomFrom,out); + writeLittleEndian((int)serverZoomTo,out); + + // The master persists + writeLittleEndian((int)notesMasterPersist,out); + writeLittleEndian((int)handoutMasterPersist,out); + + // The ID of the first slide + writeLittleEndian((short)firstSlideNum,out); + + // The slide size type + writeLittleEndian((short)slideSizeType,out); + + // The booleans as bytes + out.write(saveWithFonts); + out.write(omitTitlePlace); + out.write(rightToLeft); + out.write(showComments); + + // Reserved data + out.write(reserved); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + final Map<String, Supplier<?>> m = new LinkedHashMap<>(); + m.put("slideSizeX", this::getSlideSizeX); + m.put("slideSizeY", this::getSlideSizeY); + m.put("notesSizeX", this::getNotesSizeX); + m.put("notesSizeY", this::getNotesSizeY); + m.put("serverZoomFrom", this::getServerZoomFrom); + m.put("serverZoomTo", this::getServerZoomTo); + m.put("notesMasterPersist", this::getNotesMasterPersist); + m.put("handoutMasterPersist", this::getHandoutMasterPersist); + m.put("firstSlideNum", this::getFirstSlideNum); + m.put("slideSize", this::getSlideSizeTypeEnum); + m.put("saveWithFonts", this::getSaveWithFonts); + m.put("omitTitlePlace", this::getOmitTitlePlace); + m.put("rightToLeft", this::getRightToLeft); + m.put("showComments", this::getShowComments); + return Collections.unmodifiableMap(m); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocumentEncryptionAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocumentEncryptionAtom.java index c0b1d09c6d..f2f05087da 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocumentEncryptionAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DocumentEncryptionAtom.java @@ -42,101 +42,101 @@ import org.apache.poi.util.LittleEndianInputStream; */ public final class DocumentEncryptionAtom extends PositionDependentRecordAtom { private static final long _type = RecordTypes.DocumentEncryptionAtom.typeID; - private final byte[] _header; - private EncryptionInfo ei; - - /** - * For the Document Encryption Atom - */ - protected DocumentEncryptionAtom(byte[] source, int start, int len) { - // Get the header - _header = Arrays.copyOfRange(source,start,start+8); - - ByteArrayInputStream bis = new ByteArrayInputStream(source, start+8, len-8); - try (LittleEndianInputStream leis = new LittleEndianInputStream(bis)) { - ei = new EncryptionInfo(leis, EncryptionMode.cryptoAPI); - } catch (IOException e) { - throw new EncryptedDocumentException(e); - } - } - - public DocumentEncryptionAtom() { - _header = new byte[8]; - LittleEndian.putShort(_header, 0, (short)0x000F); - LittleEndian.putShort(_header, 2, (short)_type); - // record length not yet known ... - - ei = new EncryptionInfo(EncryptionMode.cryptoAPI); - } - - /** - * Initializes the encryption settings - * - * @param keyBits see {@link CipherAlgorithm#rc4} for allowed values, use -1 for default size - */ - public void initializeEncryptionInfo(int keyBits) { - ei = new EncryptionInfo(EncryptionMode.cryptoAPI, CipherAlgorithm.rc4, HashAlgorithm.sha1, keyBits, -1, null); - } - - /** - * Return the length of the encryption key, in bits - */ - public int getKeyLength() { - return ei.getHeader().getKeySize(); - } - - /** - * Return the name of the encryption provider used - */ - public String getEncryptionProviderName() { - return ei.getHeader().getCspName(); - } - - /** - * @return the {@link EncryptionInfo} object for details about encryption settings - */ - public EncryptionInfo getEncryptionInfo() { - return ei; - } - - - /** - * We are of type 12052 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - - // Data + private final byte[] _header; + private EncryptionInfo ei; + + /** + * For the Document Encryption Atom + */ + protected DocumentEncryptionAtom(byte[] source, int start, int len) { + // Get the header + _header = Arrays.copyOfRange(source,start,start+8); + + ByteArrayInputStream bis = new ByteArrayInputStream(source, start+8, len-8); + try (LittleEndianInputStream leis = new LittleEndianInputStream(bis)) { + ei = new EncryptionInfo(leis, EncryptionMode.cryptoAPI); + } catch (IOException e) { + throw new EncryptedDocumentException(e); + } + } + + public DocumentEncryptionAtom() { + _header = new byte[8]; + LittleEndian.putShort(_header, 0, (short)0x000F); + LittleEndian.putShort(_header, 2, (short)_type); + // record length not yet known ... + + ei = new EncryptionInfo(EncryptionMode.cryptoAPI); + } + + /** + * Initializes the encryption settings + * + * @param keyBits see {@link CipherAlgorithm#rc4} for allowed values, use -1 for default size + */ + public void initializeEncryptionInfo(int keyBits) { + ei = new EncryptionInfo(EncryptionMode.cryptoAPI, CipherAlgorithm.rc4, HashAlgorithm.sha1, keyBits, -1, null); + } + + /** + * Return the length of the encryption key, in bits + */ + public int getKeyLength() { + return ei.getHeader().getKeySize(); + } + + /** + * Return the name of the encryption provider used + */ + public String getEncryptionProviderName() { + return ei.getHeader().getCspName(); + } + + /** + * @return the {@link EncryptionInfo} object for details about encryption settings + */ + public EncryptionInfo getEncryptionInfo() { + return ei; + } + + + /** + * We are of type 12052 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + + // Data byte[] data = new byte[1024]; - LittleEndianByteArrayOutputStream bos = new LittleEndianByteArrayOutputStream(data, 0); - bos.writeShort(ei.getVersionMajor()); - bos.writeShort(ei.getVersionMinor()); - bos.writeInt(ei.getEncryptionFlags()); + LittleEndianByteArrayOutputStream bos = new LittleEndianByteArrayOutputStream(data, 0); + bos.writeShort(ei.getVersionMajor()); + bos.writeShort(ei.getVersionMinor()); + bos.writeInt(ei.getEncryptionFlags()); - ((CryptoAPIEncryptionHeader)ei.getHeader()).write(bos); - ((CryptoAPIEncryptionVerifier)ei.getVerifier()).write(bos); + ((CryptoAPIEncryptionHeader)ei.getHeader()).write(bos); + ((CryptoAPIEncryptionVerifier)ei.getVerifier()).write(bos); // Header - LittleEndian.putInt(_header, 4, bos.getWriteIndex()); + LittleEndian.putInt(_header, 4, bos.getWriteIndex()); out.write(_header); - out.write(data, 0, bos.getWriteIndex()); - bos.close(); - } + out.write(data, 0, bos.getWriteIndex()); + bos.close(); + } @Override public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup) { // nothing to update } - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "encryptionInfo", this::getEncryptionInfo - ); - } + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "encryptionInfo", this::getEncryptionInfo + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DummyPositionSensitiveRecordWithChildren.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DummyPositionSensitiveRecordWithChildren.java index 526bc363d8..3a27d27f44 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DummyPositionSensitiveRecordWithChildren.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DummyPositionSensitiveRecordWithChildren.java @@ -35,32 +35,32 @@ import org.apache.poi.util.LittleEndian; public final class DummyPositionSensitiveRecordWithChildren extends PositionDependentRecordContainer { - private byte[] _header; - private long _type; + private byte[] _header; + private long _type; - /** - * Create a new holder for a boring record with children, but with - * position dependent characteristics - */ - protected DummyPositionSensitiveRecordWithChildren(byte[] source, int start, int len) { - // Just grab the header, not the whole contents - _header = Arrays.copyOfRange(source,start,start+8); - _type = LittleEndian.getUShort(_header,2); + /** + * Create a new holder for a boring record with children, but with + * position dependent characteristics + */ + protected DummyPositionSensitiveRecordWithChildren(byte[] source, int start, int len) { + // Just grab the header, not the whole contents + _header = Arrays.copyOfRange(source,start,start+8); + _type = LittleEndian.getUShort(_header,2); - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - } + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + } - /** - * Return the value we were given at creation - */ - public long getRecordType() { return _type; } + /** + * Return the value we were given at creation + */ + public long getRecordType() { return _type; } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DummyRecordWithChildren.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DummyRecordWithChildren.java index 93e5aa3cca..22eae1ef8b 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DummyRecordWithChildren.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DummyRecordWithChildren.java @@ -31,31 +31,31 @@ import org.apache.poi.util.LittleEndian; public final class DummyRecordWithChildren extends RecordContainer { - private byte[] _header; - private long _type; - - /** - * Create a new holder for a boring record with children - */ - protected DummyRecordWithChildren(byte[] source, int start, int len) { - // Just grab the header, not the whole contents - _header = Arrays.copyOfRange(source, start, start+8); - _type = LittleEndian.getUShort(_header,2); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - } - - /** - * Return the value we were given at creation - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + private byte[] _header; + private long _type; + + /** + * Create a new holder for a boring record with children + */ + protected DummyRecordWithChildren(byte[] source, int start, int len) { + // Just grab the header, not the whole contents + _header = Arrays.copyOfRange(source, start, start+8); + _type = LittleEndian.getUShort(_header,2); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + } + + /** + * Return the value we were given at creation + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Environment.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Environment.java index 25d5820ec4..8845454ded 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Environment.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Environment.java @@ -27,58 +27,58 @@ import java.util.Arrays; public final class Environment extends PositionDependentRecordContainer { - private byte[] _header; - private static long _type = 1010; + private byte[] _header; + private static long _type = 1010; - // Links to our more interesting children - private FontCollection fontCollection; + // Links to our more interesting children + private FontCollection fontCollection; //master style for text with type=TextHeaderAtom.OTHER_TYPE private TxMasterStyleAtom txmaster; - /** - * Returns the FontCollection of this Environment - */ - public FontCollection getFontCollection() { return fontCollection; } + /** + * Returns the FontCollection of this Environment + */ + public FontCollection getFontCollection() { return fontCollection; } - /** - * Set things up, and find our more interesting children - */ - protected Environment(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); + /** + * Set things up, and find our more interesting children + */ + protected Environment(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); - // Find our FontCollection record - for(int i=0; i<_children.length; i++) { - if(_children[i] instanceof FontCollection) { - fontCollection = (FontCollection)_children[i]; - } else if (_children[i] instanceof TxMasterStyleAtom){ + // Find our FontCollection record + for(int i=0; i<_children.length; i++) { + if(_children[i] instanceof FontCollection) { + fontCollection = (FontCollection)_children[i]; + } else if (_children[i] instanceof TxMasterStyleAtom){ txmaster = (TxMasterStyleAtom)_children[i]; } - } + } - if(fontCollection == null) { - throw new IllegalStateException("Environment didn't contain a FontCollection record!"); - } - } + if(fontCollection == null) { + throw new IllegalStateException("Environment didn't contain a FontCollection record!"); + } + } public TxMasterStyleAtom getTxMasterStyleAtom(){ return txmaster; } - /** - * We are of type 1010 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + /** + * We are of type 1010 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/EscherTextboxWrapper.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/EscherTextboxWrapper.java index 751bf291f9..7f9b70bcfc 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/EscherTextboxWrapper.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/EscherTextboxWrapper.java @@ -34,99 +34,99 @@ import org.apache.poi.util.GenericRecordUtil; * parent PPDrawing) will do the actual write out */ public final class EscherTextboxWrapper extends RecordContainer { - private final EscherTextboxRecord _escherRecord; - private long _type; - private int shapeId; - private StyleTextPropAtom styleTextPropAtom; - private StyleTextProp9Atom styleTextProp9Atom; - - /** - * Returns the underlying DDF Escher Record - */ - public EscherTextboxRecord getEscherRecord() { return _escherRecord; } - - /** - * Creates the wrapper for the given DDF Escher Record and children - */ - public EscherTextboxWrapper(EscherTextboxRecord textbox) { - _escherRecord = textbox; - _type = _escherRecord.getRecordId(); - - // Find the child records in the escher data - byte[] data = _escherRecord.getData(); - _children = Record.findChildRecords(data,0,data.length); - for (org.apache.poi.hslf.record.Record r : this._children) { - if (r instanceof StyleTextPropAtom) { this.styleTextPropAtom = (StyleTextPropAtom) r; } - } - } - - /** - * Creates a new, empty wrapper for DDF Escher Records and their children - */ - public EscherTextboxWrapper() { - _escherRecord = new EscherTextboxRecord(); - _escherRecord.setRecordId(EscherTextboxRecord.RECORD_ID); - _escherRecord.setOptions((short)15); - - _children = new org.apache.poi.hslf.record.Record[0]; - } - - - /** - * Return the type of the escher record (normally in the 0xFnnn range) - */ - @Override - public long getRecordType() { return _type; } - - /** - * Stores the data for the child records back into the Escher layer. - * Doesn't actually do the writing out, that's left to the Escher - * layer to do. Must be called before writeOut/serialize is called - * on the underlying Escher object! - */ - @Override - public void writeOut(OutputStream out) throws IOException { - // Write out our children, and stuff them into the Escher layer - - // Grab the children's data - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - for (org.apache.poi.hslf.record.Record r : _children) r.writeOut(baos); - byte[] data = baos.toByteArray(); - - // Save in the escher layer - _escherRecord.setData(data); - } - - /** - * @return Shape ID - */ - public int getShapeId(){ - return shapeId; - } - - /** - * @param id Shape ID - */ - public void setShapeId(int id){ - shapeId = id; - } - - public StyleTextPropAtom getStyleTextPropAtom() { - return styleTextPropAtom; - } - - public void setStyleTextProp9Atom(final StyleTextProp9Atom nineAtom) { - this.styleTextProp9Atom = nineAtom; - } - public StyleTextProp9Atom getStyleTextProp9Atom() { - return this.styleTextProp9Atom; - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "shapeId", this::getShapeId, - "escherRecord", this::getEscherRecord - ); - } + private final EscherTextboxRecord _escherRecord; + private long _type; + private int shapeId; + private StyleTextPropAtom styleTextPropAtom; + private StyleTextProp9Atom styleTextProp9Atom; + + /** + * Returns the underlying DDF Escher Record + */ + public EscherTextboxRecord getEscherRecord() { return _escherRecord; } + + /** + * Creates the wrapper for the given DDF Escher Record and children + */ + public EscherTextboxWrapper(EscherTextboxRecord textbox) { + _escherRecord = textbox; + _type = _escherRecord.getRecordId(); + + // Find the child records in the escher data + byte[] data = _escherRecord.getData(); + _children = Record.findChildRecords(data,0,data.length); + for (org.apache.poi.hslf.record.Record r : this._children) { + if (r instanceof StyleTextPropAtom) { this.styleTextPropAtom = (StyleTextPropAtom) r; } + } + } + + /** + * Creates a new, empty wrapper for DDF Escher Records and their children + */ + public EscherTextboxWrapper() { + _escherRecord = new EscherTextboxRecord(); + _escherRecord.setRecordId(EscherTextboxRecord.RECORD_ID); + _escherRecord.setOptions((short)15); + + _children = new org.apache.poi.hslf.record.Record[0]; + } + + + /** + * Return the type of the escher record (normally in the 0xFnnn range) + */ + @Override + public long getRecordType() { return _type; } + + /** + * Stores the data for the child records back into the Escher layer. + * Doesn't actually do the writing out, that's left to the Escher + * layer to do. Must be called before writeOut/serialize is called + * on the underlying Escher object! + */ + @Override + public void writeOut(OutputStream out) throws IOException { + // Write out our children, and stuff them into the Escher layer + + // Grab the children's data + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + for (org.apache.poi.hslf.record.Record r : _children) r.writeOut(baos); + byte[] data = baos.toByteArray(); + + // Save in the escher layer + _escherRecord.setData(data); + } + + /** + * @return Shape ID + */ + public int getShapeId(){ + return shapeId; + } + + /** + * @param id Shape ID + */ + public void setShapeId(int id){ + shapeId = id; + } + + public StyleTextPropAtom getStyleTextPropAtom() { + return styleTextPropAtom; + } + + public void setStyleTextProp9Atom(final StyleTextProp9Atom nineAtom) { + this.styleTextProp9Atom = nineAtom; + } + public StyleTextProp9Atom getStyleTextProp9Atom() { + return this.styleTextProp9Atom; + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "shapeId", this::getShapeId, + "escherRecord", this::getEscherRecord + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExEmbedAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExEmbedAtom.java index 1841a6deda..08ac291bdf 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExEmbedAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExEmbedAtom.java @@ -100,7 +100,7 @@ public class ExEmbedAtom extends RecordAtom { // Must be at least 8 bytes long if(_data.length < 8) { - throw new IllegalArgumentException("The length of the data for a ExEmbedAtom must be at least 4 bytes, but was only " + _data.length); + throw new IllegalArgumentException("The length of the data for a ExEmbedAtom must be at least 4 bytes, but was only " + _data.length); } } @@ -125,7 +125,7 @@ public class ExEmbedAtom extends RecordAtom { } public void setCantLockServerB(boolean cantBeLocked) { - _data[4] = (byte)(cantBeLocked ? 1 : 0); + _data[4] = (byte)(cantBeLocked ? 1 : 0); } /** diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExHyperlink.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExHyperlink.java index 0d20be1424..c3e3639525 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExHyperlink.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExHyperlink.java @@ -28,28 +28,28 @@ import static org.apache.logging.log4j.util.Unbox.box; * This class represents the data of a link in the document. */ public class ExHyperlink extends RecordContainer { - private static final long _type = RecordTypes.ExHyperlink.typeID; + private static final long _type = RecordTypes.ExHyperlink.typeID; - private byte[] _header; + private byte[] _header; - // Links to our more interesting children - private ExHyperlinkAtom linkAtom; - private CString linkDetailsA; - private CString linkDetailsB; + // Links to our more interesting children + private ExHyperlinkAtom linkAtom; + private CString linkDetailsA; + private CString linkDetailsB; - /** - * Returns the ExHyperlinkAtom of this link - */ - public ExHyperlinkAtom getExHyperlinkAtom() { return linkAtom; } + /** + * Returns the ExHyperlinkAtom of this link + */ + public ExHyperlinkAtom getExHyperlinkAtom() { return linkAtom; } - /** - * Returns the URL of the link. + /** + * Returns the URL of the link. * * @return the URL of the link - */ - public String getLinkURL() { - return linkDetailsB == null ? null : linkDetailsB.getText(); - } + */ + public String getLinkURL() { + return linkDetailsB == null ? null : linkDetailsB.getText(); + } /** * Returns the hyperlink's user-readable name @@ -60,15 +60,15 @@ public class ExHyperlink extends RecordContainer { return linkDetailsA == null ? null : linkDetailsA.getText(); } - /** - * Sets the URL of the link - * TODO: Figure out if we should always set both - */ - public void setLinkURL(String url) { - if(linkDetailsB != null) { - linkDetailsB.setText(url); - } - } + /** + * Sets the URL of the link + * TODO: Figure out if we should always set both + */ + public void setLinkURL(String url) { + if(linkDetailsB != null) { + linkDetailsB.setText(url); + } + } public void setLinkOptions(int options) { if(linkDetailsB != null) { @@ -82,49 +82,49 @@ public class ExHyperlink extends RecordContainer { } } - /** - * Get the link details (field A) - */ - public String _getDetailsA() { - return linkDetailsA == null ? null : linkDetailsA.getText(); - } - /** - * Get the link details (field B) - */ - public String _getDetailsB() { - return linkDetailsB == null ? null : linkDetailsB.getText(); - } - - /** - * Set things up, and find our more interesting children - */ - protected ExHyperlink(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - findInterestingChildren(); - } - - /** - * Go through our child records, picking out the ones that are - * interesting, and saving those for use by the easy helper - * methods. - */ - private void findInterestingChildren() { - - // First child should be the ExHyperlinkAtom - Record child = _children[0]; - if(child instanceof ExHyperlinkAtom) { - linkAtom = (ExHyperlinkAtom) child; - } else { - LOG.atError().log("First child record wasn't a ExHyperlinkAtom, was of type {}", box(child.getRecordType())); - } + /** + * Get the link details (field A) + */ + public String _getDetailsA() { + return linkDetailsA == null ? null : linkDetailsA.getText(); + } + /** + * Get the link details (field B) + */ + public String _getDetailsB() { + return linkDetailsB == null ? null : linkDetailsB.getText(); + } + + /** + * Set things up, and find our more interesting children + */ + protected ExHyperlink(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + findInterestingChildren(); + } + + /** + * Go through our child records, picking out the ones that are + * interesting, and saving those for use by the easy helper + * methods. + */ + private void findInterestingChildren() { + + // First child should be the ExHyperlinkAtom + Record child = _children[0]; + if(child instanceof ExHyperlinkAtom) { + linkAtom = (ExHyperlinkAtom) child; + } else { + LOG.atError().log("First child record wasn't a ExHyperlinkAtom, was of type {}", box(child.getRecordType())); + } for (int i = 1; i < _children.length; i++) { - child = _children[i]; - if (child instanceof CString){ + child = _children[i]; + if (child instanceof CString){ if ( linkDetailsA == null) linkDetailsA = (CString) child; else linkDetailsB = (CString) child; } else { @@ -132,40 +132,40 @@ public class ExHyperlink extends RecordContainer { } } - } - - /** - * Create a new ExHyperlink, with blank fields - */ - public ExHyperlink() { - _header = new byte[8]; - _children = new org.apache.poi.hslf.record.Record[3]; - - // Setup our header block - _header[0] = 0x0f; // We are a container record - LittleEndian.putShort(_header, 2, (short)_type); - - // Setup our child records - CString csa = new CString(); - CString csb = new CString(); - csa.setOptions(0x00); - csb.setOptions(0x10); - _children[0] = new ExHyperlinkAtom(); - _children[1] = csa; - _children[2] = csb; - findInterestingChildren(); - } - - /** - * We are of type 4055 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + } + + /** + * Create a new ExHyperlink, with blank fields + */ + public ExHyperlink() { + _header = new byte[8]; + _children = new org.apache.poi.hslf.record.Record[3]; + + // Setup our header block + _header[0] = 0x0f; // We are a container record + LittleEndian.putShort(_header, 2, (short)_type); + + // Setup our child records + CString csa = new CString(); + CString csb = new CString(); + csa.setOptions(0x00); + csb.setOptions(0x10); + _children[0] = new ExHyperlinkAtom(); + _children[1] = csa; + _children[2] = csb; + findInterestingChildren(); + } + + /** + * We are of type 4055 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExHyperlinkAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExHyperlinkAtom.java index 104973c8ca..a0765a43e3 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExHyperlinkAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExHyperlinkAtom.java @@ -76,7 +76,7 @@ public final class ExHyperlinkAtom extends RecordAtom { // Must be at least 4 bytes long if(_data.length < 4) { - throw new IllegalArgumentException("The length of the data for a ExHyperlinkAtom must be at least 4 bytes, but was only " + _data.length); + throw new IllegalArgumentException("The length of the data for a ExHyperlinkAtom must be at least 4 bytes, but was only " + _data.length); } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjList.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjList.java index 86437d8df0..ccd0975d6f 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjList.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjList.java @@ -27,85 +27,85 @@ import org.apache.poi.util.LittleEndian; * This class holds the links to exernal objects referenced from the document. */ public class ExObjList extends RecordContainer { - private byte[] _header; - private static final long _type = RecordTypes.ExObjList.typeID; - - // Links to our more interesting children - private ExObjListAtom exObjListAtom; - - /** - * Returns the ExObjListAtom of this list - */ - public ExObjListAtom getExObjListAtom() { return exObjListAtom; } - - /** - * Returns all the ExHyperlinks - */ - public ExHyperlink[] getExHyperlinks() { - ArrayList<ExHyperlink> links = new ArrayList<>(); - for(int i=0; i<_children.length; i++) { - if(_children[i] instanceof ExHyperlink) { - links.add( (ExHyperlink)_children[i] ); - } - } - - return links.toArray(new ExHyperlink[0]); - } - - /** - * Set things up, and find our more interesting children - */ - protected ExObjList(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - findInterestingChildren(); - } - - /** - * Go through our child records, picking out the ones that are - * interesting, and saving those for use by the easy helper - * methods. - */ - private void findInterestingChildren() { - // First child should be the atom - if(_children[0] instanceof ExObjListAtom) { - exObjListAtom = (ExObjListAtom)_children[0]; - } else { - throw new IllegalStateException("First child record wasn't a ExObjListAtom, was of type " + _children[0].getRecordType()); - } - } - - /** - * Create a new ExObjList, with blank fields - */ - public ExObjList() { - _header = new byte[8]; - _children = new org.apache.poi.hslf.record.Record[1]; - - // Setup our header block - _header[0] = 0x0f; // We are a container record - LittleEndian.putShort(_header, 2, (short)_type); - - // Setup our child records - _children[0] = new ExObjListAtom(); - findInterestingChildren(); - } - - /** - * We are of type 1033 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + private byte[] _header; + private static final long _type = RecordTypes.ExObjList.typeID; + + // Links to our more interesting children + private ExObjListAtom exObjListAtom; + + /** + * Returns the ExObjListAtom of this list + */ + public ExObjListAtom getExObjListAtom() { return exObjListAtom; } + + /** + * Returns all the ExHyperlinks + */ + public ExHyperlink[] getExHyperlinks() { + ArrayList<ExHyperlink> links = new ArrayList<>(); + for(int i=0; i<_children.length; i++) { + if(_children[i] instanceof ExHyperlink) { + links.add( (ExHyperlink)_children[i] ); + } + } + + return links.toArray(new ExHyperlink[0]); + } + + /** + * Set things up, and find our more interesting children + */ + protected ExObjList(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + findInterestingChildren(); + } + + /** + * Go through our child records, picking out the ones that are + * interesting, and saving those for use by the easy helper + * methods. + */ + private void findInterestingChildren() { + // First child should be the atom + if(_children[0] instanceof ExObjListAtom) { + exObjListAtom = (ExObjListAtom)_children[0]; + } else { + throw new IllegalStateException("First child record wasn't a ExObjListAtom, was of type " + _children[0].getRecordType()); + } + } + + /** + * Create a new ExObjList, with blank fields + */ + public ExObjList() { + _header = new byte[8]; + _children = new org.apache.poi.hslf.record.Record[1]; + + // Setup our header block + _header[0] = 0x0f; // We are a container record + LittleEndian.putShort(_header, 2, (short)_type); + + // Setup our child records + _children[0] = new ExObjListAtom(); + findInterestingChildren(); + } + + /** + * We are of type 1033 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } /** * Lookup a hyperlink by its unique id diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjListAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjListAtom.java index 3b5b7125d2..9bd90201d4 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjListAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjListAtom.java @@ -78,7 +78,7 @@ public class ExObjListAtom extends RecordAtom // Must be at least 4 bytes long if(_data.length < 4) { - throw new IllegalArgumentException("The length of the data for a ExObjListAtom must be at least 4 bytes, but was only " + _data.length); + throw new IllegalArgumentException("The length of the data for a ExObjListAtom must be at least 4 bytes, but was only " + _data.length); } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjRefAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjRefAtom.java index a1e3d168c8..3a3fee5c84 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjRefAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExObjRefAtom.java @@ -34,14 +34,14 @@ import org.apache.poi.util.LittleEndian; */ public final class ExObjRefAtom extends RecordAtom { - private byte[] _header; + private byte[] _header; - /** - * A 4-byte unsigned integer that specifies a reference to an external object. - * It MUST be equal to the value of the exObjId field of an ExMediaAtom record - * or the value of the exObjId field of an ExOleObjAtom record. - */ - private int exObjIdRef; + /** + * A 4-byte unsigned integer that specifies a reference to an external object. + * It MUST be equal to the value of the exObjId field of an ExMediaAtom record + * or the value of the exObjId field of an ExOleObjAtom record. + */ + private int exObjIdRef; /** * Create a new instance of <code>ExObjRefAtom</code> @@ -61,16 +61,16 @@ public final class ExObjRefAtom extends RecordAtom { * @param start the start offset into the byte array. * @param len the length of the slice in the byte array. */ - protected ExObjRefAtom(byte[] source, int start, int len) { + protected ExObjRefAtom(byte[] source, int start, int len) { _header = Arrays.copyOfRange(source, start, start+8); exObjIdRef = (int)LittleEndian.getUInt(source, start+8); - } + } /** * @return type of this record {@link RecordTypes#ExObjRefAtom}. */ - public long getRecordType() { - return RecordTypes.ExObjRefAtom.typeID; + public long getRecordType() { + return RecordTypes.ExObjRefAtom.typeID; } public int getExObjIdRef(){ @@ -82,17 +82,17 @@ public final class ExObjRefAtom extends RecordAtom { } /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - out.write(_header); + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); byte[] recdata = new byte[4]; LittleEndian.putUInt(recdata, 0, exObjIdRef); out.write(recdata); - } + } @Override public Map<String, Supplier<?>> getGenericProperties() { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExOleObjAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExOleObjAtom.java index 321f09cb41..5906eca9c0 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExOleObjAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExOleObjAtom.java @@ -195,7 +195,7 @@ public class ExOleObjAtom extends RecordAtom { // 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); + throw new IllegalArgumentException("The length of the data for a ExOleObjAtom must be at least 24 bytes, but was only " + _data.length); } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExVideoContainer.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExVideoContainer.java index 9c3398a359..c1543bd20c 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExVideoContainer.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ExVideoContainer.java @@ -29,73 +29,73 @@ import static org.apache.logging.log4j.util.Unbox.box; * A container record that specifies information about external video data. */ public final class ExVideoContainer extends RecordContainer { - private byte[] _header; + private byte[] _header; - // Links to our more interesting children - private ExMediaAtom mediaAtom; + // Links to our more interesting children + private ExMediaAtom mediaAtom; //the UNC or local path to a video file. private CString pathAtom; - /** - * Set things up, and find our more interesting children - */ - protected ExVideoContainer(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - findInterestingChildren(); - } - - /** - * Go through our child records, picking out the ones that are - * interesting, and saving those for use by the easy helper - * methods. - */ - private void findInterestingChildren() { - - // First child should be the ExMediaAtom - Record child = _children[0]; - if(child instanceof ExMediaAtom) { - mediaAtom = (ExMediaAtom) child; - } else { - LOG.atError().log("First child record wasn't a ExMediaAtom, was of type {}", box(child.getRecordType())); - } - child = _children[1]; - if(child instanceof CString) { + /** + * Set things up, and find our more interesting children + */ + protected ExVideoContainer(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + findInterestingChildren(); + } + + /** + * Go through our child records, picking out the ones that are + * interesting, and saving those for use by the easy helper + * methods. + */ + private void findInterestingChildren() { + + // First child should be the ExMediaAtom + Record child = _children[0]; + if(child instanceof ExMediaAtom) { + mediaAtom = (ExMediaAtom) child; + } else { + LOG.atError().log("First child record wasn't a ExMediaAtom, was of type {}", box(child.getRecordType())); + } + child = _children[1]; + if(child instanceof CString) { pathAtom = (CString) child; } else { LOG.atError().log("Second child record wasn't a CString, was of type {}", box(child.getRecordType())); } - } + } - /** - * Create a new ExVideoContainer, with blank fields - */ - public ExVideoContainer() { + /** + * Create a new ExVideoContainer, with blank fields + */ + public ExVideoContainer() { // Setup our header block - _header = new byte[8]; - _header[0] = 0x0f; // We are a container record - LittleEndian.putShort(_header, 2, (short)getRecordType()); + _header = new byte[8]; + _header[0] = 0x0f; // We are a container record + LittleEndian.putShort(_header, 2, (short)getRecordType()); _children = new org.apache.poi.hslf.record.Record[2]; - _children[0] = mediaAtom = new ExMediaAtom(); - _children[1] = pathAtom = new CString(); - } - - /** - * We are of type 4103 - */ - public long getRecordType() { return RecordTypes.ExVideoContainer.typeID; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],getRecordType(),_children,out); - } + _children[0] = mediaAtom = new ExMediaAtom(); + _children[1] = pathAtom = new CString(); + } + + /** + * We are of type 4103 + */ + public long getRecordType() { return RecordTypes.ExVideoContainer.typeID; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],getRecordType(),_children,out); + } /** * Returns the ExMediaAtom of this link diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/FontCollection.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/FontCollection.java index 665824fcc8..70dcfca0fe 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/FontCollection.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/FontCollection.java @@ -46,42 +46,42 @@ public final class FontCollection extends RecordContainer { private final Map<Integer,HSLFFontInfo> fonts = new LinkedHashMap<>(); private byte[] _header; - /* package */ FontCollection(byte[] source, int start, int len) { + /* package */ FontCollection(byte[] source, int start, int len) { _header = Arrays.copyOfRange(source, start, start+8); - _children = Record.findChildRecords(source,start+8,len-8); + _children = Record.findChildRecords(source,start+8,len-8); - for (org.apache.poi.hslf.record.Record r : _children){ - if(r instanceof FontEntityAtom) { + for (org.apache.poi.hslf.record.Record r : _children){ + if(r instanceof FontEntityAtom) { HSLFFontInfo fi = new HSLFFontInfo((FontEntityAtom) r); fonts.put(fi.getIndex(), fi); } else if (r instanceof FontEmbeddedData) { FontEmbeddedData fed = (FontEmbeddedData)r; - FontHeader fontHeader = fed.getFontHeader(); - HSLFFontInfo fi = addFont(fontHeader); - fi.addFacet(fed); - } else { - LOG.atWarn().log("FontCollection child wasn't a FontEntityAtom, was {}", r.getClass().getSimpleName()); - } - } - } - - /** - * Return the type, which is 2005 - */ - @Override + FontHeader fontHeader = fed.getFontHeader(); + HSLFFontInfo fi = addFont(fontHeader); + fi.addFacet(fed); + } else { + LOG.atWarn().log("FontCollection child wasn't a FontEntityAtom, was {}", r.getClass().getSimpleName()); + } + } + } + + /** + * Return the type, which is 2005 + */ + @Override public long getRecordType() { return RecordTypes.FontCollection.typeID; } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],getRecordType(),_children,out); - } + writeOut(_header[0],_header[1],getRecordType(),_children,out); + } /** * Add font with the given FontInfo configuration to the font collection. diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/FontEntityAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/FontEntityAtom.java index 4ba09c1892..43c1f15190 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/FontEntityAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/FontEntityAtom.java @@ -62,21 +62,21 @@ public final class FontEntityAtom extends RecordAtom { */ private final byte[] _header; - /** + /** * record data */ - private byte[] _recdata; + private byte[] _recdata; /** * Build an instance of <code>FontEntityAtom</code> from on-disk data */ - /* package */ FontEntityAtom(byte[] source, int start, int len) { - // Get the header + /* package */ FontEntityAtom(byte[] source, int start, int len) { + // Get the header _header = Arrays.copyOfRange(source, start, start+8); - // Grab the record data - _recdata = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); - } + // Grab the record data + _recdata = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); + } /** * Create a new instance of <code>FontEntityAtom</code> @@ -97,19 +97,19 @@ public final class FontEntityAtom extends RecordAtom { /** * A null-terminated string that specifies the typeface name of the font. * The length of this string must not exceed 32 characters - * including the null terminator. + * including the null terminator. * @return font name */ public String getFontName(){ - final int maxLen = Math.min(_recdata.length,64)/2; - return StringUtil.getFromUnicodeLE0Terminated(_recdata, 0, maxLen); + final int maxLen = Math.min(_recdata.length,64)/2; + return StringUtil.getFromUnicodeLE0Terminated(_recdata, 0, maxLen); } /** * Set the name of the font. * The length of this string must not exceed 32 characters - * including the null terminator. - * Will be converted to null-terminated if not already + * including the null terminator. + * Will be converted to null-terminated if not already * @param name of the font */ public void setFontName(String name) { @@ -220,13 +220,13 @@ public final class FontEntityAtom extends RecordAtom { } /** - * Write the contents of the record back, so it can be written to disk - */ - @Override + * Write the contents of the record back, so it can be written to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - out.write(_header); - out.write(_recdata); - } + out.write(_header); + out.write(_recdata); + } @Override public Map<String, Supplier<?>> getGenericProperties() { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/HeadersFootersAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/HeadersFootersAtom.java index 049776f5e2..eca4eb2704 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/HeadersFootersAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/HeadersFootersAtom.java @@ -131,21 +131,21 @@ public final class HeadersFootersAtom extends RecordAtom { */ private final byte[] _header; - /** + /** * record data */ - private final byte[] _recdata; + private final byte[] _recdata; /** * Build an instance of {@code HeadersFootersAtom} from on-disk data */ - protected HeadersFootersAtom(byte[] source, int start, int len) { - // Get the header + protected HeadersFootersAtom(byte[] source, int start, int len) { + // Get the header _header = Arrays.copyOfRange(source, start, start+8); - // Grab the record data - _recdata = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); - } + // Grab the record data + _recdata = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); + } /** * Create a new instance of {@code HeadersFootersAtom} @@ -164,13 +164,13 @@ public final class HeadersFootersAtom extends RecordAtom { } /** - * Write the contents of the record back, so it can be written to disk - */ - @Override + * Write the contents of the record back, so it can be written to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - out.write(_header); - out.write(_recdata); - } + out.write(_header); + out.write(_recdata); + } /** * A signed integer that specifies the format ID to be used to style the datetime. diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/InteractiveInfo.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/InteractiveInfo.java index 63826003a0..62f1b693f0 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/InteractiveInfo.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/InteractiveInfo.java @@ -28,70 +28,70 @@ import org.apache.poi.util.LittleEndian; * in it. */ public class InteractiveInfo extends RecordContainer { - private byte[] _header; - private static final long _type = RecordTypes.InteractiveInfo.typeID; + private byte[] _header; + private static final long _type = RecordTypes.InteractiveInfo.typeID; - // Links to our more interesting children - private InteractiveInfoAtom infoAtom; + // Links to our more interesting children + private InteractiveInfoAtom infoAtom; - /** - * Returns the InteractiveInfoAtom of this InteractiveInfo - */ - public InteractiveInfoAtom getInteractiveInfoAtom() { return infoAtom; } + /** + * Returns the InteractiveInfoAtom of this InteractiveInfo + */ + public InteractiveInfoAtom getInteractiveInfoAtom() { return infoAtom; } - /** - * Set things up, and find our more interesting children - */ - protected InteractiveInfo(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); + /** + * Set things up, and find our more interesting children + */ + protected InteractiveInfo(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - findInterestingChildren(); - } + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + findInterestingChildren(); + } - /** - * Go through our child records, picking out the ones that are - * interesting, and saving those for use by the easy helper - * methods. - */ - private void findInterestingChildren() { - // First child should be the InteractiveInfoAtom - if (_children == null || _children.length == 0 || !(_children[0] instanceof InteractiveInfoAtom)) { - LOG.atWarn().log("First child record wasn't a InteractiveInfoAtom - leaving this atom in an invalid state..."); - return; - } + /** + * Go through our child records, picking out the ones that are + * interesting, and saving those for use by the easy helper + * methods. + */ + private void findInterestingChildren() { + // First child should be the InteractiveInfoAtom + if (_children == null || _children.length == 0 || !(_children[0] instanceof InteractiveInfoAtom)) { + LOG.atWarn().log("First child record wasn't a InteractiveInfoAtom - leaving this atom in an invalid state..."); + return; + } - infoAtom = (InteractiveInfoAtom)_children[0]; - } + infoAtom = (InteractiveInfoAtom)_children[0]; + } - /** - * Create a new InteractiveInfo, with blank fields - */ - public InteractiveInfo() { - _header = new byte[8]; - _children = new org.apache.poi.hslf.record.Record[1]; + /** + * Create a new InteractiveInfo, with blank fields + */ + public InteractiveInfo() { + _header = new byte[8]; + _children = new org.apache.poi.hslf.record.Record[1]; - // Setup our header block - _header[0] = 0x0f; // We are a container record - LittleEndian.putShort(_header, 2, (short)_type); + // Setup our header block + _header[0] = 0x0f; // We are a container record + LittleEndian.putShort(_header, 2, (short)_type); - // Setup our child records - infoAtom = new InteractiveInfoAtom(); - _children[0] = infoAtom; - } + // Setup our child records + infoAtom = new InteractiveInfoAtom(); + _children[0] = infoAtom; + } - /** - * We are of type 4802 - */ - public long getRecordType() { return _type; } + /** + * We are of type 4802 + */ + public long getRecordType() { return _type; } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/InteractiveInfoAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/InteractiveInfoAtom.java index e5e5ccbb6c..fbe51f35eb 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/InteractiveInfoAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/InteractiveInfoAtom.java @@ -158,7 +158,7 @@ public class InteractiveInfoAtom extends RecordAtom { // Must be at least 16 bytes long if(_data.length < 16) { - throw new IllegalArgumentException("The length of the data for a InteractiveInfoAtom must be at least 16 bytes, but was only " + _data.length); + throw new IllegalArgumentException("The length of the data for a InteractiveInfoAtom must be at least 16 bytes, but was only " + _data.length); } // First 4 bytes - no idea, normally 0 @@ -197,7 +197,7 @@ public class InteractiveInfoAtom extends RecordAtom { * @param val a reference to a sound in the sound collection */ public void setSoundRef(int val) { - LittleEndian.putInt(_data, 0, val); + LittleEndian.putInt(_data, 0, val); } /** @@ -221,7 +221,7 @@ public class InteractiveInfoAtom extends RecordAtom { * @param val hyperlink action. */ public void setAction(byte val) { - _data[8] = val; + _data[8] = val; } /** @@ -235,7 +235,7 @@ public class InteractiveInfoAtom extends RecordAtom { * Only valid when action == OLEAction. OLE verb to use, 0 = first verb, 1 = second verb, etc. */ public void setOleVerb(byte val) { - _data[9] = val; + _data[9] = val; } /** @@ -259,7 +259,7 @@ public class InteractiveInfoAtom extends RecordAtom { * @param val jump */ public void setJump(byte val) { - _data[10] = val; + _data[10] = val; } /** @@ -285,7 +285,7 @@ public class InteractiveInfoAtom extends RecordAtom { * </ul> */ public void setFlags(byte val) { - _data[11] = val; + _data[11] = val; } /** @@ -303,7 +303,7 @@ public class InteractiveInfoAtom extends RecordAtom { * @param val hyperlink type */ public void setHyperlinkType(byte val) { - _data[12] = val; + _data[12] = val; } /** diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/MainMaster.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/MainMaster.java index 62c475de46..cc9aaf1f5a 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/MainMaster.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/MainMaster.java @@ -26,78 +26,78 @@ import java.util.Arrays; * Master slide */ public final class MainMaster extends SheetContainer { - private byte[] _header; - private static long _type = 1016; - - // Links to our more interesting children - private SlideAtom slideAtom; - private PPDrawing ppDrawing; - private TxMasterStyleAtom[] txmasters; - private ColorSchemeAtom[] clrscheme; - private ColorSchemeAtom _colorScheme; - - /** - * Returns the SlideAtom of this Slide - */ - public SlideAtom getSlideAtom() { return slideAtom; } - - /** - * Returns the PPDrawing of this Slide, which has all the - * interesting data in it - */ - public PPDrawing getPPDrawing() { return ppDrawing; } - - public TxMasterStyleAtom[] getTxMasterStyleAtoms() { return txmasters; } - - public ColorSchemeAtom[] getColorSchemeAtoms() { return clrscheme; } - - /** - * Set things up, and find our more interesting children - */ - protected MainMaster(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - - ArrayList<TxMasterStyleAtom> tx = new ArrayList<>(); - ArrayList<ColorSchemeAtom> clr = new ArrayList<>(); - // Find the interesting ones in there - for (Record child : _children) { - if (child instanceof SlideAtom) { - slideAtom = (SlideAtom) child; - } else if (child instanceof PPDrawing) { - ppDrawing = (PPDrawing) child; - } else if (child instanceof TxMasterStyleAtom) { - tx.add((TxMasterStyleAtom) child); - } else if (child instanceof ColorSchemeAtom) { - clr.add((ColorSchemeAtom) child); - } - - if (ppDrawing != null && child instanceof ColorSchemeAtom) { - _colorScheme = (ColorSchemeAtom) child; - } - - } - txmasters = tx.toArray(new TxMasterStyleAtom[0]); - clrscheme = clr.toArray(new ColorSchemeAtom[0]); - } - - /** - * We are of type 1016 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } - - public ColorSchemeAtom getColorScheme(){ - return _colorScheme; - } + private byte[] _header; + private static long _type = 1016; + + // Links to our more interesting children + private SlideAtom slideAtom; + private PPDrawing ppDrawing; + private TxMasterStyleAtom[] txmasters; + private ColorSchemeAtom[] clrscheme; + private ColorSchemeAtom _colorScheme; + + /** + * Returns the SlideAtom of this Slide + */ + public SlideAtom getSlideAtom() { return slideAtom; } + + /** + * Returns the PPDrawing of this Slide, which has all the + * interesting data in it + */ + public PPDrawing getPPDrawing() { return ppDrawing; } + + public TxMasterStyleAtom[] getTxMasterStyleAtoms() { return txmasters; } + + public ColorSchemeAtom[] getColorSchemeAtoms() { return clrscheme; } + + /** + * Set things up, and find our more interesting children + */ + protected MainMaster(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + + ArrayList<TxMasterStyleAtom> tx = new ArrayList<>(); + ArrayList<ColorSchemeAtom> clr = new ArrayList<>(); + // Find the interesting ones in there + for (Record child : _children) { + if (child instanceof SlideAtom) { + slideAtom = (SlideAtom) child; + } else if (child instanceof PPDrawing) { + ppDrawing = (PPDrawing) child; + } else if (child instanceof TxMasterStyleAtom) { + tx.add((TxMasterStyleAtom) child); + } else if (child instanceof ColorSchemeAtom) { + clr.add((ColorSchemeAtom) child); + } + + if (ppDrawing != null && child instanceof ColorSchemeAtom) { + _colorScheme = (ColorSchemeAtom) child; + } + + } + txmasters = tx.toArray(new TxMasterStyleAtom[0]); + clrscheme = clr.toArray(new ColorSchemeAtom[0]); + } + + /** + * We are of type 1016 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } + + public ColorSchemeAtom getColorScheme(){ + return _colorScheme; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Notes.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Notes.java index b53842f70f..dacbde35c8 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Notes.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Notes.java @@ -28,62 +28,62 @@ import java.util.Arrays; public final class Notes extends SheetContainer { - private byte[] _header; - private static long _type = 1008l; + private byte[] _header; + private static long _type = 1008l; - // Links to our more interesting children - private NotesAtom notesAtom; - private PPDrawing ppDrawing; + // Links to our more interesting children + private NotesAtom notesAtom; + private PPDrawing ppDrawing; private ColorSchemeAtom _colorScheme; - /** - * Returns the NotesAtom of this Notes - */ - public NotesAtom getNotesAtom() { return notesAtom; } - /** - * Returns the PPDrawing of this Notes, which has all the - * interesting data in it - */ - public PPDrawing getPPDrawing() { return ppDrawing; } - - - /** - * Set things up, and find our more interesting children - */ - protected Notes(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - - // Find the interesting ones in there - for (Record child : _children) { - if (child instanceof NotesAtom) { - notesAtom = (NotesAtom) child; - } - if (child instanceof PPDrawing) { - ppDrawing = (PPDrawing) child; - } - if (ppDrawing != null && child instanceof ColorSchemeAtom) { - _colorScheme = (ColorSchemeAtom) child; - } - } - } - - - /** - * We are of type 1008 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + /** + * Returns the NotesAtom of this Notes + */ + public NotesAtom getNotesAtom() { return notesAtom; } + /** + * Returns the PPDrawing of this Notes, which has all the + * interesting data in it + */ + public PPDrawing getPPDrawing() { return ppDrawing; } + + + /** + * Set things up, and find our more interesting children + */ + protected Notes(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + + // Find the interesting ones in there + for (Record child : _children) { + if (child instanceof NotesAtom) { + notesAtom = (NotesAtom) child; + } + if (child instanceof PPDrawing) { + ppDrawing = (PPDrawing) child; + } + if (ppDrawing != null && child instanceof ColorSchemeAtom) { + _colorScheme = (ColorSchemeAtom) child; + } + } + } + + + /** + * We are of type 1008 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } public ColorSchemeAtom getColorScheme(){ return _colorScheme; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/NotesAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/NotesAtom.java index 74fb25f27e..5e4664293d 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/NotesAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/NotesAtom.java @@ -35,89 +35,89 @@ import org.apache.poi.util.LittleEndian; public final class NotesAtom extends RecordAtom { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; - - private byte[] _header; - private static long _type = 1009l; - - private int slideID; - private boolean followMasterObjects; - private boolean followMasterScheme; - private boolean followMasterBackground; - private byte[] reserved; - - - public int getSlideID() { return slideID; } - public void setSlideID(int id) { slideID = id; } - - public boolean getFollowMasterObjects() { return followMasterObjects; } - public boolean getFollowMasterScheme() { return followMasterScheme; } - public boolean getFollowMasterBackground() { return followMasterBackground; } - public void setFollowMasterObjects(boolean flag) { followMasterObjects = flag; } - public void setFollowMasterScheme(boolean flag) { followMasterScheme = flag; } - public void setFollowMasterBackground(boolean flag) { followMasterBackground = flag; } - - - /* *************** record code follows ********************** */ - - /** - * For the Notes Atom - */ - protected NotesAtom(byte[] source, int start, int len) { - // Sanity Checking - if(len < 8) { len = 8; } - - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Get the slide ID - slideID = LittleEndian.getInt(source,start+8); - - // Grok the flags, stored as bits - int flags = LittleEndian.getUShort(source,start+12); - followMasterBackground = (flags & 4) == 4; - followMasterScheme = (flags & 2) == 2; - followMasterObjects = (flags & 1) == 1; - - // There might be 2 more bytes, which are a reserved field - reserved = IOUtils.safelyClone(source, start+14, len-14, MAX_RECORD_LENGTH); - } - - /** - * We are of type 1009 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - // Header - out.write(_header); - - // Slide ID - writeLittleEndian(slideID,out); - - // Flags - short flags = 0; - if(followMasterObjects) { flags += 1; } - if(followMasterScheme) { flags += 2; } - if(followMasterBackground) { flags += 4; } - writeLittleEndian(flags,out); - - // Reserved fields - out.write(reserved); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "slideId", this::getSlideID, - "followMasterObjects", this::getFollowMasterObjects, - "followMasterScheme", this::getFollowMasterScheme, - "followMasterBackground", this::getFollowMasterBackground - ); - } + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + + private byte[] _header; + private static long _type = 1009l; + + private int slideID; + private boolean followMasterObjects; + private boolean followMasterScheme; + private boolean followMasterBackground; + private byte[] reserved; + + + public int getSlideID() { return slideID; } + public void setSlideID(int id) { slideID = id; } + + public boolean getFollowMasterObjects() { return followMasterObjects; } + public boolean getFollowMasterScheme() { return followMasterScheme; } + public boolean getFollowMasterBackground() { return followMasterBackground; } + public void setFollowMasterObjects(boolean flag) { followMasterObjects = flag; } + public void setFollowMasterScheme(boolean flag) { followMasterScheme = flag; } + public void setFollowMasterBackground(boolean flag) { followMasterBackground = flag; } + + + /* *************** record code follows ********************** */ + + /** + * For the Notes Atom + */ + protected NotesAtom(byte[] source, int start, int len) { + // Sanity Checking + if(len < 8) { len = 8; } + + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Get the slide ID + slideID = LittleEndian.getInt(source,start+8); + + // Grok the flags, stored as bits + int flags = LittleEndian.getUShort(source,start+12); + followMasterBackground = (flags & 4) == 4; + followMasterScheme = (flags & 2) == 2; + followMasterObjects = (flags & 1) == 1; + + // There might be 2 more bytes, which are a reserved field + reserved = IOUtils.safelyClone(source, start+14, len-14, MAX_RECORD_LENGTH); + } + + /** + * We are of type 1009 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + // Header + out.write(_header); + + // Slide ID + writeLittleEndian(slideID,out); + + // Flags + short flags = 0; + if(followMasterObjects) { flags += 1; } + if(followMasterScheme) { flags += 2; } + if(followMasterBackground) { flags += 4; } + writeLittleEndian(flags,out); + + // Reserved fields + out.write(reserved); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "slideId", this::getSlideID, + "followMasterObjects", this::getFollowMasterObjects, + "followMasterScheme", this::getFollowMasterScheme, + "followMasterBackground", this::getFollowMasterBackground + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/OEPlaceholderAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/OEPlaceholderAtom.java index af3595fecb..bfc038747c 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/OEPlaceholderAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/OEPlaceholderAtom.java @@ -52,7 +52,7 @@ public final class OEPlaceholderAtom extends RecordAtom{ */ public static final int PLACEHOLDER_QUARTSIZE = 2; - private byte[] _header; + private byte[] _header; private int placementId; private int placeholderId; @@ -77,7 +77,7 @@ public final class OEPlaceholderAtom extends RecordAtom{ /** * Build an instance of {@code OEPlaceholderAtom} from on-disk data */ - protected OEPlaceholderAtom(byte[] source, int start, int len) { + protected OEPlaceholderAtom(byte[] source, int start, int len) { _header = Arrays.copyOfRange(source, start, start+8); int offset = start+8; @@ -85,12 +85,12 @@ public final class OEPlaceholderAtom extends RecordAtom{ placeholderId = LittleEndian.getUByte(source, offset); offset++; placeholderSize = LittleEndian.getUByte(source, offset); offset++; unusedShort = LittleEndian.getShort(source, offset); - } + } /** * @return type of this record {@link RecordTypes#OEPlaceholderAtom}. */ - @Override + @Override public long getRecordType() { return RecordTypes.OEPlaceholderAtom.typeID; } /** @@ -163,12 +163,12 @@ public final class OEPlaceholderAtom extends RecordAtom{ placeholderSize = size; } - /** - * Write the contents of the record back, so it can be written to disk - */ - @Override + /** + * Write the contents of the record back, so it can be written to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - out.write(_header); + out.write(_header); byte[] recdata = new byte[8]; LittleEndian.putInt(recdata, 0, placementId); @@ -177,7 +177,7 @@ public final class OEPlaceholderAtom extends RecordAtom{ LittleEndian.putShort(recdata, 6, unusedShort); out.write(recdata); - } + } @Override public Map<String, Supplier<?>> getGenericProperties() { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PPDrawing.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PPDrawing.java index 396fbc06f4..2140678d26 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PPDrawing.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PPDrawing.java @@ -64,34 +64,34 @@ import org.apache.poi.util.LittleEndian; // would require a wrapping class public final class PPDrawing extends RecordAtom implements Iterable<EscherRecord> { - private final byte[] _header; - private long _type; + private final byte[] _header; + private long _type; - private EscherTextboxWrapper[] textboxWrappers; + private EscherTextboxWrapper[] textboxWrappers; - private final EscherContainerRecord dgContainer = new EscherContainerRecord(); + private final EscherContainerRecord dgContainer = new EscherContainerRecord(); - //cached EscherDgRecord - private EscherDgRecord dg; + //cached EscherDgRecord + private EscherDgRecord dg; - /** - * Get access to the underlying Escher Records - */ - @SuppressWarnings("WeakerAccess") - public List<EscherRecord> getEscherRecords() { return Collections.singletonList(dgContainer); } + /** + * Get access to the underlying Escher Records + */ + @SuppressWarnings("WeakerAccess") + public List<EscherRecord> getEscherRecords() { return Collections.singletonList(dgContainer); } - @Override - public Iterator<EscherRecord> iterator() { - return getEscherRecords().iterator(); - } + @Override + public Iterator<EscherRecord> iterator() { + return getEscherRecords().iterator(); + } - /** - * Get access to the atoms inside Textboxes - */ - public EscherTextboxWrapper[] getTextboxWrappers() { return textboxWrappers; } + /** + * Get access to the atoms inside Textboxes + */ + public EscherTextboxWrapper[] getTextboxWrappers() { return textboxWrappers; } - /* ******************** record stuff follows ********************** */ + /* ******************** record stuff follows ********************** */ /** * Creates a new, empty, PPDrawing (typically for use with a new Slide @@ -107,223 +107,223 @@ public final class PPDrawing extends RecordAtom implements Iterable<EscherRecord create(); } - /** - * Sets everything up, groks the escher etc - */ - PPDrawing(byte[] source, int start, int len) { - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Get the type - _type = LittleEndian.getUShort(_header,2); - - // Build up a tree of Escher records contained within - final DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory(); - dgContainer.fillFields(source, start + 8, erf); - assert dgContainer.getRecordId() == EscherRecordTypes.DG_CONTAINER.typeID; - dg = dgContainer.getChildById(EscherRecordTypes.DG.typeID); - - textboxWrappers = Stream.of(dgContainer). - flatMap(findEscherContainer(EscherRecordTypes.SPGR_CONTAINER)). - flatMap(findEscherContainer(EscherRecordTypes.SP_CONTAINER)). - flatMap(PPDrawing::getTextboxHelper). - toArray(EscherTextboxWrapper[]::new); - } - - private static Stream<EscherTextboxWrapper> getTextboxHelper(EscherContainerRecord spContainer) { - Optional<EscherTextboxRecord> oTB = firstEscherRecord(spContainer, EscherRecordTypes.CLIENT_TEXTBOX); - if (!oTB.isPresent()) { - return Stream.empty(); - } - - EscherTextboxWrapper tbw = new EscherTextboxWrapper(oTB.get()); - findInSpContainer(spContainer).ifPresent(tbw::setStyleTextProp9Atom); - - Optional<EscherSpRecord> oSP = firstEscherRecord(spContainer, EscherRecordTypes.SP); - oSP.map(EscherSpRecord::getShapeId).ifPresent(tbw::setShapeId); - - return Stream.of(tbw); - } - - private static Optional<StyleTextProp9Atom> findInSpContainer(final EscherContainerRecord spContainer) { - Optional<HSLFEscherClientDataRecord> oCD = firstEscherRecord(spContainer, EscherRecordTypes.CLIENT_DATA); - return oCD.map(HSLFEscherClientDataRecord::getHSLFChildRecords).map(List::stream).orElseGet(Stream::empty). - filter(sameHSLF(RecordTypes.ProgTags)). - flatMap(r -> Stream.of(r.getChildRecords())). - filter(sameHSLF(RecordTypes.ProgBinaryTag)). - flatMap(PPDrawing::findInProgBinaryTag). - findFirst(); - } - - private static Stream<StyleTextProp9Atom> findInProgBinaryTag(org.apache.poi.hslf.record.Record r) { - Record[] ch = r.getChildRecords(); - if (ch != null && - ch.length == 2 && - ch[0] instanceof CString && - ch[1] instanceof BinaryTagDataBlob && - "___PPT9".equals(((CString)ch[0]).getText()) - ) { - BinaryTagDataBlob blob = (BinaryTagDataBlob) ch[1]; - StyleTextProp9Atom prop9 = (StyleTextProp9Atom) blob.findFirstOfType(RecordTypes.StyleTextProp9Atom.typeID); - if (prop9 != null) { - return Stream.of(prop9); - } - } - return Stream.empty(); - } - - /** - * We are type 1036 - */ - public long getRecordType() { return _type; } - - /** - * We're pretending to be an atom, so return null - */ - public org.apache.poi.hslf.record.Record[] getChildRecords() { return null; } - - /** - * Write the contents of the record back, so it can be written - * to disk - * Walks the escher layer to get the contents - */ - public void writeOut(OutputStream out) throws IOException { - // Ensure the escher layer reflects the text changes - for (EscherTextboxWrapper w : textboxWrappers) { - w.writeOut(null); - } - - // Find the new size of the escher children; - int newSize = 0; - newSize += dgContainer.getRecordSize(); - - // Update the size (header bytes 5-8) - LittleEndian.putInt(_header,4,newSize); - - // Write out our header - out.write(_header); - - // Now grab the children's data - byte[] b = new byte[newSize]; - int done = 0; - dgContainer.serialize(done, b); - - // Finally, write out the children - out.write(b); - } - - /** - * Create the Escher records associated with a new PPDrawing - */ - private void create(){ - dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER ); - dgContainer.setOptions((short)15); - - dg = new EscherDgRecord(); - dg.setOptions((short)16); - dg.setNumShapes(1); - dgContainer.addChildRecord(dg); - - EscherContainerRecord spgrContainer = new EscherContainerRecord(); - spgrContainer.setOptions((short)15); - spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); - - EscherContainerRecord spContainer = new EscherContainerRecord(); - spContainer.setOptions((short)15); - spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); - - EscherSpgrRecord spgr = new EscherSpgrRecord(); - spgr.setOptions((short)1); - spContainer.addChildRecord(spgr); - - EscherSpRecord sp = new EscherSpRecord(); - sp.setOptions((short)((ShapeType.NOT_PRIMITIVE.nativeId << 4) + 2)); - sp.setFlags(EscherSpRecord.FLAG_PATRIARCH | EscherSpRecord.FLAG_GROUP); - spContainer.addChildRecord(sp); - spgrContainer.addChildRecord(spContainer); - dgContainer.addChildRecord(spgrContainer); - - spContainer = new EscherContainerRecord(); - spContainer.setOptions((short)15); - spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); - sp = new EscherSpRecord(); - sp.setOptions((short)((ShapeType.RECT.nativeId << 4) + 2)); - sp.setFlags(EscherSpRecord.FLAG_BACKGROUND | EscherSpRecord.FLAG_HASSHAPETYPE); - spContainer.addChildRecord(sp); - - EscherOptRecord opt = new EscherOptRecord(); - opt.setRecordId(EscherOptRecord.RECORD_ID); - opt.addEscherProperty(new EscherRGBProperty(EscherPropertyTypes.FILL__FILLCOLOR, 134217728)); - opt.addEscherProperty(new EscherRGBProperty(EscherPropertyTypes.FILL__FILLBACKCOLOR, 134217733)); - opt.addEscherProperty(new EscherSimpleProperty(EscherPropertyTypes.FILL__RECTRIGHT, 10064750)); - opt.addEscherProperty(new EscherSimpleProperty(EscherPropertyTypes.FILL__RECTBOTTOM, 7778750)); - opt.addEscherProperty(new EscherBoolProperty(EscherPropertyTypes.FILL__NOFILLHITTEST, 1179666)); - opt.addEscherProperty(new EscherBoolProperty(EscherPropertyTypes.LINESTYLE__NOLINEDRAWDASH, 524288)); - opt.addEscherProperty(new EscherSimpleProperty(EscherPropertyTypes.SHAPE__BLACKANDWHITESETTINGS, 9)); - opt.addEscherProperty(new EscherSimpleProperty(EscherPropertyTypes.SHAPE__BACKGROUNDSHAPE, 65537)); - spContainer.addChildRecord(opt); - - dgContainer.addChildRecord(spContainer); - } - - /** - * Add a new EscherTextboxWrapper to this <code>PPDrawing</code>. - */ - public void addTextboxWrapper(EscherTextboxWrapper txtbox){ - EscherTextboxWrapper[] tw = new EscherTextboxWrapper[textboxWrappers.length + 1]; - System.arraycopy(textboxWrappers, 0, tw, 0, textboxWrappers.length); - - tw[textboxWrappers.length] = txtbox; - textboxWrappers = tw; - } - - /** - * @return the container record for drawings - * @since POI 3.14-Beta2 - */ - public EscherContainerRecord getDgContainer() { - return dgContainer; - } - - /** - * Return EscherDgRecord which keeps track of the number of shapes and shapeId in this drawing group - * - * @return EscherDgRecord - */ - public EscherDgRecord getEscherDgRecord(){ - return dg; - } + /** + * Sets everything up, groks the escher etc + */ + PPDrawing(byte[] source, int start, int len) { + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Get the type + _type = LittleEndian.getUShort(_header,2); + + // Build up a tree of Escher records contained within + final DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory(); + dgContainer.fillFields(source, start + 8, erf); + assert dgContainer.getRecordId() == EscherRecordTypes.DG_CONTAINER.typeID; + dg = dgContainer.getChildById(EscherRecordTypes.DG.typeID); + + textboxWrappers = Stream.of(dgContainer). + flatMap(findEscherContainer(EscherRecordTypes.SPGR_CONTAINER)). + flatMap(findEscherContainer(EscherRecordTypes.SP_CONTAINER)). + flatMap(PPDrawing::getTextboxHelper). + toArray(EscherTextboxWrapper[]::new); + } + + private static Stream<EscherTextboxWrapper> getTextboxHelper(EscherContainerRecord spContainer) { + Optional<EscherTextboxRecord> oTB = firstEscherRecord(spContainer, EscherRecordTypes.CLIENT_TEXTBOX); + if (!oTB.isPresent()) { + return Stream.empty(); + } + + EscherTextboxWrapper tbw = new EscherTextboxWrapper(oTB.get()); + findInSpContainer(spContainer).ifPresent(tbw::setStyleTextProp9Atom); + + Optional<EscherSpRecord> oSP = firstEscherRecord(spContainer, EscherRecordTypes.SP); + oSP.map(EscherSpRecord::getShapeId).ifPresent(tbw::setShapeId); + + return Stream.of(tbw); + } + + private static Optional<StyleTextProp9Atom> findInSpContainer(final EscherContainerRecord spContainer) { + Optional<HSLFEscherClientDataRecord> oCD = firstEscherRecord(spContainer, EscherRecordTypes.CLIENT_DATA); + return oCD.map(HSLFEscherClientDataRecord::getHSLFChildRecords).map(List::stream).orElseGet(Stream::empty). + filter(sameHSLF(RecordTypes.ProgTags)). + flatMap(r -> Stream.of(r.getChildRecords())). + filter(sameHSLF(RecordTypes.ProgBinaryTag)). + flatMap(PPDrawing::findInProgBinaryTag). + findFirst(); + } + + private static Stream<StyleTextProp9Atom> findInProgBinaryTag(org.apache.poi.hslf.record.Record r) { + Record[] ch = r.getChildRecords(); + if (ch != null && + ch.length == 2 && + ch[0] instanceof CString && + ch[1] instanceof BinaryTagDataBlob && + "___PPT9".equals(((CString)ch[0]).getText()) + ) { + BinaryTagDataBlob blob = (BinaryTagDataBlob) ch[1]; + StyleTextProp9Atom prop9 = (StyleTextProp9Atom) blob.findFirstOfType(RecordTypes.StyleTextProp9Atom.typeID); + if (prop9 != null) { + return Stream.of(prop9); + } + } + return Stream.empty(); + } + + /** + * We are type 1036 + */ + public long getRecordType() { return _type; } + + /** + * We're pretending to be an atom, so return null + */ + public org.apache.poi.hslf.record.Record[] getChildRecords() { return null; } + + /** + * Write the contents of the record back, so it can be written + * to disk + * Walks the escher layer to get the contents + */ + public void writeOut(OutputStream out) throws IOException { + // Ensure the escher layer reflects the text changes + for (EscherTextboxWrapper w : textboxWrappers) { + w.writeOut(null); + } + + // Find the new size of the escher children; + int newSize = 0; + newSize += dgContainer.getRecordSize(); + + // Update the size (header bytes 5-8) + LittleEndian.putInt(_header,4,newSize); + + // Write out our header + out.write(_header); + + // Now grab the children's data + byte[] b = new byte[newSize]; + int done = 0; + dgContainer.serialize(done, b); + + // Finally, write out the children + out.write(b); + } + + /** + * Create the Escher records associated with a new PPDrawing + */ + private void create(){ + dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER ); + dgContainer.setOptions((short)15); + + dg = new EscherDgRecord(); + dg.setOptions((short)16); + dg.setNumShapes(1); + dgContainer.addChildRecord(dg); + + EscherContainerRecord spgrContainer = new EscherContainerRecord(); + spgrContainer.setOptions((short)15); + spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); + + EscherContainerRecord spContainer = new EscherContainerRecord(); + spContainer.setOptions((short)15); + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + + EscherSpgrRecord spgr = new EscherSpgrRecord(); + spgr.setOptions((short)1); + spContainer.addChildRecord(spgr); + + EscherSpRecord sp = new EscherSpRecord(); + sp.setOptions((short)((ShapeType.NOT_PRIMITIVE.nativeId << 4) + 2)); + sp.setFlags(EscherSpRecord.FLAG_PATRIARCH | EscherSpRecord.FLAG_GROUP); + spContainer.addChildRecord(sp); + spgrContainer.addChildRecord(spContainer); + dgContainer.addChildRecord(spgrContainer); + + spContainer = new EscherContainerRecord(); + spContainer.setOptions((short)15); + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + sp = new EscherSpRecord(); + sp.setOptions((short)((ShapeType.RECT.nativeId << 4) + 2)); + sp.setFlags(EscherSpRecord.FLAG_BACKGROUND | EscherSpRecord.FLAG_HASSHAPETYPE); + spContainer.addChildRecord(sp); + + EscherOptRecord opt = new EscherOptRecord(); + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.addEscherProperty(new EscherRGBProperty(EscherPropertyTypes.FILL__FILLCOLOR, 134217728)); + opt.addEscherProperty(new EscherRGBProperty(EscherPropertyTypes.FILL__FILLBACKCOLOR, 134217733)); + opt.addEscherProperty(new EscherSimpleProperty(EscherPropertyTypes.FILL__RECTRIGHT, 10064750)); + opt.addEscherProperty(new EscherSimpleProperty(EscherPropertyTypes.FILL__RECTBOTTOM, 7778750)); + opt.addEscherProperty(new EscherBoolProperty(EscherPropertyTypes.FILL__NOFILLHITTEST, 1179666)); + opt.addEscherProperty(new EscherBoolProperty(EscherPropertyTypes.LINESTYLE__NOLINEDRAWDASH, 524288)); + opt.addEscherProperty(new EscherSimpleProperty(EscherPropertyTypes.SHAPE__BLACKANDWHITESETTINGS, 9)); + opt.addEscherProperty(new EscherSimpleProperty(EscherPropertyTypes.SHAPE__BACKGROUNDSHAPE, 65537)); + spContainer.addChildRecord(opt); + + dgContainer.addChildRecord(spContainer); + } + + /** + * Add a new EscherTextboxWrapper to this <code>PPDrawing</code>. + */ + public void addTextboxWrapper(EscherTextboxWrapper txtbox){ + EscherTextboxWrapper[] tw = new EscherTextboxWrapper[textboxWrappers.length + 1]; + System.arraycopy(textboxWrappers, 0, tw, 0, textboxWrappers.length); + + tw[textboxWrappers.length] = txtbox; + textboxWrappers = tw; + } + + /** + * @return the container record for drawings + * @since POI 3.14-Beta2 + */ + public EscherContainerRecord getDgContainer() { + return dgContainer; + } + + /** + * Return EscherDgRecord which keeps track of the number of shapes and shapeId in this drawing group + * + * @return EscherDgRecord + */ + public EscherDgRecord getEscherDgRecord(){ + return dg; + } public StyleTextProp9Atom[] getNumberedListInfo() { - return Stream.of(dgContainer). - flatMap(findEscherContainer(EscherRecordTypes.SPGR_CONTAINER)). - flatMap(findEscherContainer(EscherRecordTypes.SP_CONTAINER)). - map(PPDrawing::findInSpContainer). - filter(Optional::isPresent). - map(Optional::get). - toArray(StyleTextProp9Atom[]::new); + return Stream.of(dgContainer). + flatMap(findEscherContainer(EscherRecordTypes.SPGR_CONTAINER)). + flatMap(findEscherContainer(EscherRecordTypes.SP_CONTAINER)). + map(PPDrawing::findInSpContainer). + filter(Optional::isPresent). + map(Optional::get). + toArray(StyleTextProp9Atom[]::new); } - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties("escherRecords", this::getEscherRecords); - } + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties("escherRecords", this::getEscherRecords); + } - private static Predicate<org.apache.poi.hslf.record.Record> sameHSLF(RecordTypes type) { - return (p) -> p.getRecordType() == type.typeID; - } + private static Predicate<org.apache.poi.hslf.record.Record> sameHSLF(RecordTypes type) { + return (p) -> p.getRecordType() == type.typeID; + } - private static Predicate<EscherRecord> sameEscher(EscherRecordTypes type) { - return (p) -> p.getRecordId() == type.typeID; - } + private static Predicate<EscherRecord> sameEscher(EscherRecordTypes type) { + return (p) -> p.getRecordId() == type.typeID; + } - @SuppressWarnings("unchecked") - private static <T extends EscherRecord> Optional<T> firstEscherRecord(Iterable<EscherRecord> container, EscherRecordTypes type) { - return StreamSupport.stream(container.spliterator(), false).filter(sameEscher(type)).map(o -> (T)o).findFirst(); - } + @SuppressWarnings("unchecked") + private static <T extends EscherRecord> Optional<T> firstEscherRecord(Iterable<EscherRecord> container, EscherRecordTypes type) { + return StreamSupport.stream(container.spliterator(), false).filter(sameEscher(type)).map(o -> (T)o).findFirst(); + } - private static Function<EscherContainerRecord,Stream<EscherContainerRecord>> findEscherContainer(EscherRecordTypes type) { - return (r) -> r.getChildContainers().stream().filter(sameEscher(type)); - } + private static Function<EscherContainerRecord,Stream<EscherContainerRecord>> findEscherContainer(EscherRecordTypes type) { + return (r) -> r.getChildContainers().stream().filter(sameEscher(type)); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ParentAwareRecord.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ParentAwareRecord.java index d09c8f7702..5338c1dd5e 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ParentAwareRecord.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/ParentAwareRecord.java @@ -22,6 +22,6 @@ package org.apache.poi.hslf.record; * parent is, and how it wants to be told which record is its parent. */ public interface ParentAwareRecord { - public org.apache.poi.hslf.record.RecordContainer getParentRecord(); - public void setParentRecord(RecordContainer parentRecord); + public org.apache.poi.hslf.record.RecordContainer getParentRecord(); + public void setParentRecord(RecordContainer parentRecord); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PersistPtrHolder.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PersistPtrHolder.java index 4e47cb7195..92772e1413 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PersistPtrHolder.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PersistPtrHolder.java @@ -48,22 +48,22 @@ import org.apache.poi.util.LittleEndianConsts; public final class PersistPtrHolder extends PositionDependentRecordAtom { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 100_000; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; - private final byte[] _header; - private byte[] _ptrData; // Will need to update this once we allow updates to _slideLocations - private final long _type; + private final byte[] _header; + private byte[] _ptrData; // Will need to update this once we allow updates to _slideLocations + private final long _type; - /** - * Holds the lookup for slides to their position on disk. - * You always need to check the most recent PersistPtrHolder - * that knows about a given slide to find the right location - */ - private final Map<Integer,Integer> _slideLocations; + /** + * Holds the lookup for slides to their position on disk. + * You always need to check the most recent PersistPtrHolder + * that knows about a given slide to find the right location + */ + private final Map<Integer,Integer> _slideLocations; - private static final BitField persistIdFld = BitFieldFactory.getInstance(0X000FFFFF); - private static final BitField cntPersistFld = BitFieldFactory.getInstance(0XFFF00000); + private static final BitField persistIdFld = BitFieldFactory.getInstance(0X000FFFFF); + private static final BitField cntPersistFld = BitFieldFactory.getInstance(0XFFF00000); /** * Return the value we were given at creation, be it 6001 or 6002 @@ -71,74 +71,74 @@ public final class PersistPtrHolder extends PositionDependentRecordAtom @Override public long getRecordType() { return _type; } - /** - * Get the list of slides that this PersistPtrHolder knows about. - * (They will be the keys in the map for looking up the positions - * of these slides) - */ - public int[] getKnownSlideIDs() { - int[] ids = new int[_slideLocations.size()]; - int i = 0; - for (Integer slideId : _slideLocations.keySet()) { - ids[i++] = slideId; - } - return ids; - } - - /** - * Get the lookup from slide numbers to byte offsets, for the slides - * known about by this PersistPtrHolder. - */ - public Map<Integer,Integer> getSlideLocationsLookup() { - return Collections.unmodifiableMap(_slideLocations); - } - - /** - * Create a new holder for a PersistPtr record - */ - protected PersistPtrHolder(byte[] source, int start, int len) { - // Sanity Checking - including whole header, so treat - // length as based of 0, not 8 (including header size based) - if(len < 8) { len = 8; } - - // Treat as an atom, grab and hold everything - _header = Arrays.copyOfRange(source, start, start+8); - _type = LittleEndian.getUShort(_header,2); - - // Try to make sense of the data part: - // Data part is made up of a number of these sets: - // 32 bit info value - // 12 bits count of # of entries - // base number for these entries - // count * 32 bit offsets - // Repeat as many times as you have data - _slideLocations = new HashMap<>(); - _ptrData = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); - - int pos = 0; - while(pos < _ptrData.length) { - // Grab the info field - int info = LittleEndian.getInt(_ptrData,pos); - - // First 20 bits = offset number - // Remaining 12 bits = offset count + /** + * Get the list of slides that this PersistPtrHolder knows about. + * (They will be the keys in the map for looking up the positions + * of these slides) + */ + public int[] getKnownSlideIDs() { + int[] ids = new int[_slideLocations.size()]; + int i = 0; + for (Integer slideId : _slideLocations.keySet()) { + ids[i++] = slideId; + } + return ids; + } + + /** + * Get the lookup from slide numbers to byte offsets, for the slides + * known about by this PersistPtrHolder. + */ + public Map<Integer,Integer> getSlideLocationsLookup() { + return Collections.unmodifiableMap(_slideLocations); + } + + /** + * Create a new holder for a PersistPtr record + */ + protected PersistPtrHolder(byte[] source, int start, int len) { + // Sanity Checking - including whole header, so treat + // length as based of 0, not 8 (including header size based) + if(len < 8) { len = 8; } + + // Treat as an atom, grab and hold everything + _header = Arrays.copyOfRange(source, start, start+8); + _type = LittleEndian.getUShort(_header,2); + + // Try to make sense of the data part: + // Data part is made up of a number of these sets: + // 32 bit info value + // 12 bits count of # of entries + // base number for these entries + // count * 32 bit offsets + // Repeat as many times as you have data + _slideLocations = new HashMap<>(); + _ptrData = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); + + int pos = 0; + while(pos < _ptrData.length) { + // Grab the info field + int info = LittleEndian.getInt(_ptrData,pos); + + // First 20 bits = offset number + // Remaining 12 bits = offset count int offset_no = persistIdFld.getValue(info); - int offset_count = cntPersistFld.getValue(info); + int offset_count = cntPersistFld.getValue(info); - // Wind on by the 4 byte info header - pos += 4; + // Wind on by the 4 byte info header + pos += 4; - // Grab the offsets for each of the sheets - for(int i=0; i<offset_count; i++) { - int sheet_no = offset_no + i; - int sheet_offset = (int)LittleEndian.getUInt(_ptrData,pos); - _slideLocations.put(sheet_no, sheet_offset); + // Grab the offsets for each of the sheets + for(int i=0; i<offset_count; i++) { + int sheet_no = offset_no + i; + int sheet_offset = (int)LittleEndian.getUInt(_ptrData,pos); + _slideLocations.put(sheet_no, sheet_offset); - // Wind on by 4 bytes per sheet found - pos += 4; - } - } - } + // Wind on by 4 bytes per sheet found + pos += 4; + } + } + } /** * remove all slide references @@ -160,88 +160,88 @@ public final class PersistPtrHolder extends PositionDependentRecordAtom _slideLocations.put(slideID, posOnDisk); } - /** - * At write-out time, update the references to the sheets to their - * new positions - */ - @Override - public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup) { - // Loop over all the slides we know about - // Find where they used to live, and where they now live - for (Entry<Integer,Integer> me : _slideLocations.entrySet()) { - Integer oldPos = me.getValue(); - Integer newPos = oldToNewReferencesLookup.get(oldPos); + /** + * At write-out time, update the references to the sheets to their + * new positions + */ + @Override + public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup) { + // Loop over all the slides we know about + // Find where they used to live, and where they now live + for (Entry<Integer,Integer> me : _slideLocations.entrySet()) { + Integer oldPos = me.getValue(); + Integer newPos = oldToNewReferencesLookup.get(oldPos); if (newPos == null) { Integer id = me.getKey(); - LOG.atWarn().log("Couldn't find the new location of the \"slide\" with id {} that used to " + - "be at {}. Not updating the position of it, you probably won't be able to find it any more " + - "(if you ever could!)", id, oldPos); + LOG.atWarn().log("Couldn't find the new location of the \"slide\" with id {} that used to " + + "be at {}. Not updating the position of it, you probably won't be able to find it any more " + + "(if you ever could!)", id, oldPos); } else { me.setValue(newPos); } - } - } - - private void normalizePersistDirectory() { - // Building the info block - // First 20 bits = offset number = slide ID (persistIdFld, i.e. first slide ID of a continuous group) - // Remaining 12 bits = offset count = 1 (cntPersistFld, i.e. continuous entries in a group) - // - // the info block is then followed by the slide offset (32 bits) - - int[] infoBlocks = new int[_slideLocations.size()*2]; - int lastSlideId = -1; - int lastPersistIdx = 0; - int lastIdx = -1; - int entryCnt = 0; - int baseSlideId = -1; - - Iterable<Entry<Integer,Integer>> iter = _slideLocations.entrySet().stream() - .sorted(Comparator.comparingInt(Entry::getKey))::iterator; - for (Entry<Integer, Integer> me : iter) { - int nextSlideId = me.getKey(); - if (lastSlideId + 1 < nextSlideId) { - // start new PersistDirectoryEntry - lastPersistIdx = ++lastIdx; - entryCnt = 0; - baseSlideId = nextSlideId; - } - - int infoBlock = persistIdFld.setValue(0, baseSlideId); - infoBlock = cntPersistFld.setValue(infoBlock, ++entryCnt); - infoBlocks[lastPersistIdx] = infoBlock; - // add the offset - infoBlocks[++lastIdx] = me.getValue(); - - lastSlideId = nextSlideId; - } - - // Save the new ptr data - _ptrData = new byte[(lastIdx+1)*LittleEndianConsts.INT_SIZE]; - for (int idx = 0; idx<=lastIdx; idx++) { - LittleEndian.putInt(_ptrData, idx*LittleEndianConsts.INT_SIZE, infoBlocks[idx]); - } - - // Update the atom header - LittleEndian.putInt(_header, 4, _ptrData.length); - } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override + } + } + + private void normalizePersistDirectory() { + // Building the info block + // First 20 bits = offset number = slide ID (persistIdFld, i.e. first slide ID of a continuous group) + // Remaining 12 bits = offset count = 1 (cntPersistFld, i.e. continuous entries in a group) + // + // the info block is then followed by the slide offset (32 bits) + + int[] infoBlocks = new int[_slideLocations.size()*2]; + int lastSlideId = -1; + int lastPersistIdx = 0; + int lastIdx = -1; + int entryCnt = 0; + int baseSlideId = -1; + + Iterable<Entry<Integer,Integer>> iter = _slideLocations.entrySet().stream() + .sorted(Comparator.comparingInt(Entry::getKey))::iterator; + for (Entry<Integer, Integer> me : iter) { + int nextSlideId = me.getKey(); + if (lastSlideId + 1 < nextSlideId) { + // start new PersistDirectoryEntry + lastPersistIdx = ++lastIdx; + entryCnt = 0; + baseSlideId = nextSlideId; + } + + int infoBlock = persistIdFld.setValue(0, baseSlideId); + infoBlock = cntPersistFld.setValue(infoBlock, ++entryCnt); + infoBlocks[lastPersistIdx] = infoBlock; + // add the offset + infoBlocks[++lastIdx] = me.getValue(); + + lastSlideId = nextSlideId; + } + + // Save the new ptr data + _ptrData = new byte[(lastIdx+1)*LittleEndianConsts.INT_SIZE]; + for (int idx = 0; idx<=lastIdx; idx++) { + LittleEndian.putInt(_ptrData, idx*LittleEndianConsts.INT_SIZE, infoBlocks[idx]); + } + + // Update the atom header + LittleEndian.putInt(_header, 4, _ptrData.length); + } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - normalizePersistDirectory(); - out.write(_header); - out.write(_ptrData); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "slideLocations", this::getSlideLocationsLookup - ); - } + normalizePersistDirectory(); + out.write(_header); + out.write(_ptrData); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "slideLocations", this::getSlideLocationsLookup + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecord.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecord.java index e71a9a7b5a..80de645882 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecord.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecord.java @@ -32,18 +32,18 @@ import java.util.Map; public interface PositionDependentRecord { - /** Fetch our location on the disk, as of the last write out */ - public int getLastOnDiskOffset(); + /** Fetch our location on the disk, as of the last write out */ + public int getLastOnDiskOffset(); - /** - * Update the Record's idea of where on disk it lives, after a write out. - * Use with care... - */ - public void setLastOnDiskOffset(int offset); + /** + * Update the Record's idea of where on disk it lives, after a write out. + * Use with care... + */ + public void setLastOnDiskOffset(int offset); - /** - * Offer the record the list of records that have changed their - * location as part of the writeout. - */ - public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup); + /** + * Offer the record the list of records that have changed their + * location as part of the writeout. + */ + public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecordAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecordAtom.java index dce90a981d..0e40b50dfb 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecordAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecordAtom.java @@ -26,25 +26,25 @@ import java.util.Map; public abstract class PositionDependentRecordAtom extends RecordAtom implements PositionDependentRecord { - /** Our location on the disk, as of the last write out */ - private int myLastOnDiskOffset; - - /** Fetch our location on the disk, as of the last write out */ - public int getLastOnDiskOffset() { return myLastOnDiskOffset; } - - /** - * Update the Record's idea of where on disk it lives, after a write out. - * Use with care... - */ - public void setLastOnDiskOffset(int offset) { - myLastOnDiskOffset = offset; - } - - /** - * Offer the record the list of records that have changed their - * location as part of the writeout. - * Allows records to update their internal pointers to other records - * locations - */ - public abstract void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup); + /** Our location on the disk, as of the last write out */ + private int myLastOnDiskOffset; + + /** Fetch our location on the disk, as of the last write out */ + public int getLastOnDiskOffset() { return myLastOnDiskOffset; } + + /** + * Update the Record's idea of where on disk it lives, after a write out. + * Use with care... + */ + public void setLastOnDiskOffset(int offset) { + myLastOnDiskOffset = offset; + } + + /** + * Offer the record the list of records that have changed their + * location as part of the writeout. + * Allows records to update their internal pointers to other records + * locations + */ + public abstract void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecordContainer.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecordContainer.java index fdd61d9cf2..820306b7c1 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecordContainer.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PositionDependentRecordContainer.java @@ -26,38 +26,38 @@ import java.util.Map; public abstract class PositionDependentRecordContainer extends RecordContainer implements PositionDependentRecord { - private int sheetId; // Found from PersistPtrHolder - - /** - * Fetch our sheet ID, as found from a PersistPtrHolder. - * Should match the RefId of our matching SlidePersistAtom - */ - public int getSheetId() { return sheetId; } - - /** - * Set our sheet ID, as found from a PersistPtrHolder - */ - public void setSheetId(int id) { sheetId = id; } - - - /** Our location on the disk, as of the last write out */ - private int myLastOnDiskOffset; - - /** Fetch our location on the disk, as of the last write out */ - public int getLastOnDiskOffset() { return myLastOnDiskOffset; } - - /** - * Update the Record's idea of where on disk it lives, after a write out. - * Use with care... - */ - public void setLastOnDiskOffset(int offset) { - myLastOnDiskOffset = offset; - } - - /** - * Since we're a container, we don't mind if other records move about. - * If we're told they have, just return straight off. - */ - public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup) { - } + private int sheetId; // Found from PersistPtrHolder + + /** + * Fetch our sheet ID, as found from a PersistPtrHolder. + * Should match the RefId of our matching SlidePersistAtom + */ + public int getSheetId() { return sheetId; } + + /** + * Set our sheet ID, as found from a PersistPtrHolder + */ + public void setSheetId(int id) { sheetId = id; } + + + /** Our location on the disk, as of the last write out */ + private int myLastOnDiskOffset; + + /** Fetch our location on the disk, as of the last write out */ + public int getLastOnDiskOffset() { return myLastOnDiskOffset; } + + /** + * Update the Record's idea of where on disk it lives, after a write out. + * Use with care... + */ + public void setLastOnDiskOffset(int offset) { + myLastOnDiskOffset = offset; + } + + /** + * Since we're a container, we don't mind if other records move about. + * If we're told they have, just return straight off. + */ + public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup) { + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Record.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Record.java index e66f481c1f..1b07189f02 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Record.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Record.java @@ -43,169 +43,169 @@ import static org.apache.logging.log4j.util.Unbox.box; public abstract class Record implements GenericRecord { // For logging - protected static final Logger LOG = LogManager.getLogger(Record.class); - - /** - * Is this record type an Atom record (only has data), - * or is it a non-Atom record (has other records)? - */ - public abstract boolean isAnAtom(); - - /** - * Returns the type (held as a little endian in bytes 3 and 4) - * that this class handles - */ - public abstract long getRecordType(); - - /** - * Fetch all the child records of this record - * If this record is an atom, will return null - * If this record is a non-atom, but has no children, will return - * an empty array - */ - public abstract Record[] getChildRecords(); - - /** - * 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 abstract void writeOut(OutputStream o) throws IOException; - - @Override - public Enum getGenericRecordType() { - return RecordTypes.forTypeID((int)getRecordType()); - } - - @Override - public List<Record> getGenericChildren() { - Record[] recs = getChildRecords(); - return (recs == null) ? null : Arrays.asList(recs); - } - - /** - * When writing out, write out a signed int (32bit) in Little Endian format - */ - public static void writeLittleEndian(int i,OutputStream o) throws IOException { - byte[] bi = new byte[4]; - LittleEndian.putInt(bi,0,i); - o.write(bi); - } - /** - * When writing out, write out a signed short (16bit) in Little Endian format - */ - public static void writeLittleEndian(short s,OutputStream o) throws IOException { - byte[] bs = new byte[2]; - LittleEndian.putShort(bs,0,s); - o.write(bs); - } - - /** - * Build and return the Record at the given offset. - * Note - does less error checking and handling than findChildRecords - * @param b The byte array to build from - * @param offset The offset to build at - */ - public static Record buildRecordAtOffset(byte[] b, int offset) { - long type = LittleEndian.getUShort(b,offset+2); - long rlen = LittleEndian.getUInt(b,offset+4); - - // Sanity check the length - int rleni = (int)rlen; - if(rleni < 0) { rleni = 0; } - - return createRecordForType(type,b,offset,8+rleni); - } - - /** - * Default method for finding child records of a container record - */ - public static Record[] findChildRecords(byte[] b, int start, int len) { - List<Record> children = new ArrayList<>(5); - - // Jump our little way along, creating records as we go - int pos = start; - while(pos <= (start+len-8)) { - long type = LittleEndian.getUShort(b,pos+2); - long rlen = LittleEndian.getUInt(b,pos+4); - - // Sanity check the length - int rleni = (int)rlen; - if(rleni < 0) { rleni = 0; } - - // Abort if first record is of type 0000 and length FFFF, - // as that's a sign of a screwed up record - if(pos == 0 && type == 0L && rleni == 0xffff) { - throw new CorruptPowerPointFileException("Corrupt document - starts with record of type 0000 and length 0xFFFF"); - } - - Record r = createRecordForType(type,b,pos,8+rleni); - if(r != null) { - children.add(r); - } - pos += 8; - pos += rleni; - } - - // Turn the vector into an array, and return + protected static final Logger LOG = LogManager.getLogger(Record.class); + + /** + * Is this record type an Atom record (only has data), + * or is it a non-Atom record (has other records)? + */ + public abstract boolean isAnAtom(); + + /** + * Returns the type (held as a little endian in bytes 3 and 4) + * that this class handles + */ + public abstract long getRecordType(); + + /** + * Fetch all the child records of this record + * If this record is an atom, will return null + * If this record is a non-atom, but has no children, will return + * an empty array + */ + public abstract Record[] getChildRecords(); + + /** + * 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 abstract void writeOut(OutputStream o) throws IOException; + + @Override + public Enum getGenericRecordType() { + return RecordTypes.forTypeID((int)getRecordType()); + } + + @Override + public List<Record> getGenericChildren() { + Record[] recs = getChildRecords(); + return (recs == null) ? null : Arrays.asList(recs); + } + + /** + * When writing out, write out a signed int (32bit) in Little Endian format + */ + public static void writeLittleEndian(int i,OutputStream o) throws IOException { + byte[] bi = new byte[4]; + LittleEndian.putInt(bi,0,i); + o.write(bi); + } + /** + * When writing out, write out a signed short (16bit) in Little Endian format + */ + public static void writeLittleEndian(short s,OutputStream o) throws IOException { + byte[] bs = new byte[2]; + LittleEndian.putShort(bs,0,s); + o.write(bs); + } + + /** + * Build and return the Record at the given offset. + * Note - does less error checking and handling than findChildRecords + * @param b The byte array to build from + * @param offset The offset to build at + */ + public static Record buildRecordAtOffset(byte[] b, int offset) { + long type = LittleEndian.getUShort(b,offset+2); + long rlen = LittleEndian.getUInt(b,offset+4); + + // Sanity check the length + int rleni = (int)rlen; + if(rleni < 0) { rleni = 0; } + + return createRecordForType(type,b,offset,8+rleni); + } + + /** + * Default method for finding child records of a container record + */ + public static Record[] findChildRecords(byte[] b, int start, int len) { + List<Record> children = new ArrayList<>(5); + + // Jump our little way along, creating records as we go + int pos = start; + while(pos <= (start+len-8)) { + long type = LittleEndian.getUShort(b,pos+2); + long rlen = LittleEndian.getUInt(b,pos+4); + + // Sanity check the length + int rleni = (int)rlen; + if(rleni < 0) { rleni = 0; } + + // Abort if first record is of type 0000 and length FFFF, + // as that's a sign of a screwed up record + if(pos == 0 && type == 0L && rleni == 0xffff) { + throw new CorruptPowerPointFileException("Corrupt document - starts with record of type 0000 and length 0xFFFF"); + } + + Record r = createRecordForType(type,b,pos,8+rleni); + if(r != null) { + children.add(r); + } + pos += 8; + pos += rleni; + } + + // Turn the vector into an array, and return return children.toArray(new Record[0]); - } - - /** - * For a given type (little endian bytes 3 and 4 in record header), - * byte array, start position and length: - * will return a Record object that will handle that record - * - * Remember that while PPT stores the record lengths as 8 bytes short - * (not including the size of the header), this code assumes you're - * passing in corrected lengths - */ - public static Record createRecordForType(long type, byte[] b, int start, int len) { - // We use the RecordTypes class to provide us with the right - // class to use for a given type - // A spot of reflection gets us the (byte[],int,int) constructor - // From there, we instanciate the class - // Any special record handling occurs once we have the class - RecordTypes recordType = RecordTypes.forTypeID((short) type); - RecordConstructor c = recordType.recordConstructor; - if (c == null) { - // How odd. RecordTypes normally substitutes in - // a default handler class if it has heard of the record - // type but there's no support for it. Explicitly request - // that now - LOG.atDebug().log(() -> new StringFormattedMessage("Known but unhandled record type %d (0x%04x) at offset %d", type, type, start)); - c = RecordTypes.UnknownRecordPlaceholder.recordConstructor; - } else if (recordType == RecordTypes.UnknownRecordPlaceholder) { - LOG.atDebug().log(() -> new StringFormattedMessage("Unknown placeholder type %d (0x%04x) at offset %d", type, type, start)); - } - - final Record toReturn; - try { - toReturn = c.apply(b, start, len); - } catch(RuntimeException e) { - // Handle case of a corrupt last record, whose claimed length - // would take us passed the end of the file - if(start + len > b.length ) { - LOG.atWarn().log("Warning: Skipping record of type {} at position {} which claims to be longer than the file! ({} vs {})", type, box(start), box(len), box(b.length - start)); - return null; - } - - throw new HSLFException("Couldn't instantiate the class for type with id " + type + " on class " + c + " : " + e, e); - } - - // Handling for special kinds of records follow - - // If it's a position aware record, tell it where it is - if(toReturn instanceof PositionDependentRecord) { - PositionDependentRecord pdr = (PositionDependentRecord)toReturn; - pdr.setLastOnDiskOffset(start); - } - - // Return the created record - return toReturn; - } + } + + /** + * For a given type (little endian bytes 3 and 4 in record header), + * byte array, start position and length: + * will return a Record object that will handle that record + * + * Remember that while PPT stores the record lengths as 8 bytes short + * (not including the size of the header), this code assumes you're + * passing in corrected lengths + */ + public static Record createRecordForType(long type, byte[] b, int start, int len) { + // We use the RecordTypes class to provide us with the right + // class to use for a given type + // A spot of reflection gets us the (byte[],int,int) constructor + // From there, we instanciate the class + // Any special record handling occurs once we have the class + RecordTypes recordType = RecordTypes.forTypeID((short) type); + RecordConstructor c = recordType.recordConstructor; + if (c == null) { + // How odd. RecordTypes normally substitutes in + // a default handler class if it has heard of the record + // type but there's no support for it. Explicitly request + // that now + LOG.atDebug().log(() -> new StringFormattedMessage("Known but unhandled record type %d (0x%04x) at offset %d", type, type, start)); + c = RecordTypes.UnknownRecordPlaceholder.recordConstructor; + } else if (recordType == RecordTypes.UnknownRecordPlaceholder) { + LOG.atDebug().log(() -> new StringFormattedMessage("Unknown placeholder type %d (0x%04x) at offset %d", type, type, start)); + } + + final Record toReturn; + try { + toReturn = c.apply(b, start, len); + } catch(RuntimeException e) { + // Handle case of a corrupt last record, whose claimed length + // would take us passed the end of the file + if(start + len > b.length ) { + LOG.atWarn().log("Warning: Skipping record of type {} at position {} which claims to be longer than the file! ({} vs {})", type, box(start), box(len), box(b.length - start)); + return null; + } + + throw new HSLFException("Couldn't instantiate the class for type with id " + type + " on class " + c + " : " + e, e); + } + + // Handling for special kinds of records follow + + // If it's a position aware record, tell it where it is + if(toReturn instanceof PositionDependentRecord) { + PositionDependentRecord pdr = (PositionDependentRecord)toReturn; + pdr.setLastOnDiskOffset(start); + } + + // Return the created record + return toReturn; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/RecordAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/RecordAtom.java index 9d2cbb1457..58b87a6355 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/RecordAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/RecordAtom.java @@ -23,13 +23,13 @@ package org.apache.poi.hslf.record; public abstract class RecordAtom extends Record { - /** - * We are an atom - */ - public boolean isAnAtom() { return true; } + /** + * We are an atom + */ + public boolean isAnAtom() { return true; } - /** - * We're an atom, returns null - */ - public org.apache.poi.hslf.record.Record[] getChildRecords() { return null; } + /** + * We're an atom, returns null + */ + public org.apache.poi.hslf.record.Record[] getChildRecords() { return null; } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/RecordContainer.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/RecordContainer.java index 98e48067c2..4815b42b74 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/RecordContainer.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/RecordContainer.java @@ -35,102 +35,102 @@ import org.apache.poi.util.LittleEndian; public abstract class RecordContainer extends Record { - protected Record[] _children; + protected Record[] _children; - /** - * Return any children - */ - @Override + /** + * Return any children + */ + @Override public org.apache.poi.hslf.record.Record[] getChildRecords() { return _children; } - /** - * We're not an atom - */ - @Override + /** + * We're not an atom + */ + @Override public boolean isAnAtom() { return false; } - /* =============================================================== - * Internal Move Helpers - * =============================================================== - */ - - /** - * Finds the location of the given child record - */ - private int findChildLocation(Record child) { - int i=0; - for(org.apache.poi.hslf.record.Record r : _children) { - if (r.equals(child)) { - return i; - } - i++; - } - return -1; - } - - /** - * Adds a child record, at the very end. - * @param newChild The child record to add - * @return the position of the added child - */ - private int appendChild(Record newChild) { - // Copy over, and pop the child in at the end - Record[] nc = Arrays.copyOf(_children, _children.length+1, org.apache.poi.hslf.record.Record[].class); - // Switch the arrays - nc[_children.length] = newChild; - _children = nc; - return _children.length; - } - - /** - * Adds the given new Child Record at the given location, - * shuffling everything from there on down by one - * - * @param newChild The record to be added as child-record. - * @param position The index where the child should be added, 0-based - */ - private void addChildAt(Record newChild, int position) { - // Firstly, have the child added in at the end - appendChild(newChild); - - // Now, have them moved to the right place - moveChildRecords( (_children.length-1), position, 1 ); - } - - /** - * Moves {@code number} child records from {@code oldLoc} to {@code newLoc}. - * @param oldLoc the current location of the records to move - * @param newLoc the new location for the records - * @param number the number of records to move - */ - private void moveChildRecords(int oldLoc, int newLoc, int number) { - if(oldLoc == newLoc) { return; } - if(number == 0) { return; } - - // Check that we're not asked to move too many - if(oldLoc+number > _children.length) { - throw new IllegalArgumentException("Asked to move more records than there are!"); - } - - // Do the move - ArrayUtil.arrayMoveWithin(_children, oldLoc, newLoc, number); - } - - - /** - * Finds the first child record of the given type, - * or null if none of the child records are of the - * given type. Does not descend. - */ - public org.apache.poi.hslf.record.Record findFirstOfType(long type) { - for (org.apache.poi.hslf.record.Record r : _children) { - if (r.getRecordType() == type) { - return r; - } - } - return null; - } + /* =============================================================== + * Internal Move Helpers + * =============================================================== + */ + + /** + * Finds the location of the given child record + */ + private int findChildLocation(Record child) { + int i=0; + for(org.apache.poi.hslf.record.Record r : _children) { + if (r.equals(child)) { + return i; + } + i++; + } + return -1; + } + + /** + * Adds a child record, at the very end. + * @param newChild The child record to add + * @return the position of the added child + */ + private int appendChild(Record newChild) { + // Copy over, and pop the child in at the end + Record[] nc = Arrays.copyOf(_children, _children.length+1, org.apache.poi.hslf.record.Record[].class); + // Switch the arrays + nc[_children.length] = newChild; + _children = nc; + return _children.length; + } + + /** + * Adds the given new Child Record at the given location, + * shuffling everything from there on down by one + * + * @param newChild The record to be added as child-record. + * @param position The index where the child should be added, 0-based + */ + private void addChildAt(Record newChild, int position) { + // Firstly, have the child added in at the end + appendChild(newChild); + + // Now, have them moved to the right place + moveChildRecords( (_children.length-1), position, 1 ); + } + + /** + * Moves {@code number} child records from {@code oldLoc} to {@code newLoc}. + * @param oldLoc the current location of the records to move + * @param newLoc the new location for the records + * @param number the number of records to move + */ + private void moveChildRecords(int oldLoc, int newLoc, int number) { + if(oldLoc == newLoc) { return; } + if(number == 0) { return; } + + // Check that we're not asked to move too many + if(oldLoc+number > _children.length) { + throw new IllegalArgumentException("Asked to move more records than there are!"); + } + + // Do the move + ArrayUtil.arrayMoveWithin(_children, oldLoc, newLoc, number); + } + + + /** + * Finds the first child record of the given type, + * or null if none of the child records are of the + * given type. Does not descend. + */ + public org.apache.poi.hslf.record.Record findFirstOfType(long type) { + for (org.apache.poi.hslf.record.Record r : _children) { + if (r.getRecordType() == type) { + return r; + } + } + return null; + } /** * Remove a child record from this record container @@ -153,55 +153,55 @@ public abstract class RecordContainer extends Record } /* =============================================================== - * External Move Methods - * =============================================================== - */ - - /** - * Add a new child record onto a record's list of children. - * - * @param newChild the child record to be added - * @return the position of the added child within the list, i.e. the last index - */ - public int appendChildRecord(Record newChild) { - return appendChild(newChild); - } - - /** - * Adds the given Child Record after the supplied record - * @param newChild The record to add as new child. - * @param after The record after which the given record should be added. - * @return the position of the added child within the list - */ - public int addChildAfter(Record newChild, Record after) { - // Decide where we're going to put it - int loc = findChildLocation(after); - if(loc == -1) { - throw new IllegalArgumentException("Asked to add a new child after another record, but that record wasn't one of our children!"); - } - - // Add one place after the supplied record - addChildAt(newChild, loc+1); - return loc+1; - } - - /** - * Adds the given Child Record before the supplied record - * @param newChild The record to add as new child. - * @param before The record before which the given record should be added. + * External Move Methods + * =============================================================== + */ + + /** + * Add a new child record onto a record's list of children. + * + * @param newChild the child record to be added + * @return the position of the added child within the list, i.e. the last index + */ + public int appendChildRecord(Record newChild) { + return appendChild(newChild); + } + + /** + * Adds the given Child Record after the supplied record + * @param newChild The record to add as new child. + * @param after The record after which the given record should be added. * @return the position of the added child within the list - */ - public int addChildBefore(Record newChild, Record before) { - // Decide where we're going to put it - int loc = findChildLocation(before); - if(loc == -1) { - throw new IllegalArgumentException("Asked to add a new child before another record, but that record wasn't one of our children!"); - } - - // Add at the place of the supplied record - addChildAt(newChild, loc); - return loc; - } + */ + public int addChildAfter(Record newChild, Record after) { + // Decide where we're going to put it + int loc = findChildLocation(after); + if(loc == -1) { + throw new IllegalArgumentException("Asked to add a new child after another record, but that record wasn't one of our children!"); + } + + // Add one place after the supplied record + addChildAt(newChild, loc+1); + return loc+1; + } + + /** + * Adds the given Child Record before the supplied record + * @param newChild The record to add as new child. + * @param before The record before which the given record should be added. + * @return the position of the added child within the list + */ + public int addChildBefore(Record newChild, Record before) { + // Decide where we're going to put it + int loc = findChildLocation(before); + if(loc == -1) { + throw new IllegalArgumentException("Asked to add a new child before another record, but that record wasn't one of our children!"); + } + + // Add at the place of the supplied record + addChildAt(newChild, loc); + return loc; + } /** * Set child records. @@ -212,46 +212,46 @@ public abstract class RecordContainer extends Record this._children = records.clone(); } - /* =============================================================== - * External Serialisation Methods - * =============================================================== - */ - - /** - * Write out our header, and our children. - * @param headerA the first byte of the header - * @param headerB the second byte of the header - * @param type the record type - * @param children our child records - * @param out the stream to write to - */ - public void writeOut(byte headerA, byte headerB, long type, Record[] children, OutputStream out) throws IOException { - // Create a UnsynchronizedByteArrayOutputStream to hold everything in - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - - // Write out our header, less the size - baos.write(new byte[] {headerA,headerB}); - byte[] typeB = new byte[2]; - LittleEndian.putShort(typeB,0,(short)type); - baos.write(typeB); - baos.write(new byte[] {0,0,0,0}); - - // Write out our children - for (Record aChildren : children) { - aChildren.writeOut(baos); - } - - // Grab the bytes back - byte[] toWrite = baos.toByteArray(); - - // Update our header with the size - // Don't forget to knock 8 more off, since we don't include the - // header in the size - LittleEndian.putInt(toWrite,4,(toWrite.length-8)); - - // Write out the bytes - out.write(toWrite); - } + /* =============================================================== + * External Serialisation Methods + * =============================================================== + */ + + /** + * Write out our header, and our children. + * @param headerA the first byte of the header + * @param headerB the second byte of the header + * @param type the record type + * @param children our child records + * @param out the stream to write to + */ + public void writeOut(byte headerA, byte headerB, long type, Record[] children, OutputStream out) throws IOException { + // Create a UnsynchronizedByteArrayOutputStream to hold everything in + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + + // Write out our header, less the size + baos.write(new byte[] {headerA,headerB}); + byte[] typeB = new byte[2]; + LittleEndian.putShort(typeB,0,(short)type); + baos.write(typeB); + baos.write(new byte[] {0,0,0,0}); + + // Write out our children + for (Record aChildren : children) { + aChildren.writeOut(baos); + } + + // Grab the bytes back + byte[] toWrite = baos.toByteArray(); + + // Update our header with the size + // Don't forget to knock 8 more off, since we don't include the + // header in the size + LittleEndian.putInt(toWrite,4,(toWrite.length-8)); + + // Write out the bytes + out.write(toWrite); + } /** * Find the records that are parent-aware, and tell them who their parent is @@ -270,8 +270,8 @@ public abstract class RecordContainer extends Record } } - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return null; - } + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return null; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Slide.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Slide.java index f8e718a9e5..20f5a7d9db 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Slide.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/Slide.java @@ -30,84 +30,84 @@ import org.apache.poi.util.LittleEndian; public final class Slide extends SheetContainer { - private byte[] _header; - private static long _type = 1006l; + private byte[] _header; + private static long _type = 1006l; - // Links to our more interesting children - private SlideAtom slideAtom; - private PPDrawing ppDrawing; + // Links to our more interesting children + private SlideAtom slideAtom; + private PPDrawing ppDrawing; private ColorSchemeAtom _colorScheme; - /** - * Returns the SlideAtom of this Slide - */ - public SlideAtom getSlideAtom() { return slideAtom; } - - /** - * Returns the PPDrawing of this Slide, which has all the - * interesting data in it - */ - public PPDrawing getPPDrawing() { return ppDrawing; } - - - /** - * Set things up, and find our more interesting children - */ - protected Slide(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - - // Find the interesting ones in there - for (Record child : _children) { - if (child instanceof SlideAtom) { - slideAtom = (SlideAtom) child; - } else if (child instanceof PPDrawing) { - ppDrawing = (PPDrawing) child; - } - - if (ppDrawing != null && child instanceof ColorSchemeAtom) { - _colorScheme = (ColorSchemeAtom) child; - } - } - } - - /** - * Create a new, empty, Slide, along with its required - * child records. - */ - public Slide(){ - _header = new byte[8]; - LittleEndian.putUShort(_header, 0, 15); - LittleEndian.putUShort(_header, 2, (int)_type); - LittleEndian.putInt(_header, 4, 0); - - slideAtom = new SlideAtom(); - ppDrawing = new PPDrawing(); - - ColorSchemeAtom colorAtom = new ColorSchemeAtom(); - - _children = new org.apache.poi.hslf.record.Record[] { - slideAtom, - ppDrawing, - colorAtom - }; - } - - /** - * We are of type 1006 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } + /** + * Returns the SlideAtom of this Slide + */ + public SlideAtom getSlideAtom() { return slideAtom; } + + /** + * Returns the PPDrawing of this Slide, which has all the + * interesting data in it + */ + public PPDrawing getPPDrawing() { return ppDrawing; } + + + /** + * Set things up, and find our more interesting children + */ + protected Slide(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + + // Find the interesting ones in there + for (Record child : _children) { + if (child instanceof SlideAtom) { + slideAtom = (SlideAtom) child; + } else if (child instanceof PPDrawing) { + ppDrawing = (PPDrawing) child; + } + + if (ppDrawing != null && child instanceof ColorSchemeAtom) { + _colorScheme = (ColorSchemeAtom) child; + } + } + } + + /** + * Create a new, empty, Slide, along with its required + * child records. + */ + public Slide(){ + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 15); + LittleEndian.putUShort(_header, 2, (int)_type); + LittleEndian.putInt(_header, 4, 0); + + slideAtom = new SlideAtom(); + ppDrawing = new PPDrawing(); + + ColorSchemeAtom colorAtom = new ColorSchemeAtom(); + + _children = new org.apache.poi.hslf.record.Record[] { + slideAtom, + ppDrawing, + colorAtom + }; + } + + /** + * We are of type 1006 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } public ColorSchemeAtom getColorScheme(){ return _colorScheme; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlideAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlideAtom.java index 5728bacf4c..3760f2d2ce 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlideAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlideAtom.java @@ -38,137 +38,137 @@ public final class SlideAtom extends RecordAtom { public static final int USES_MASTER_SLIDE_ID = 0x80000000; // private static final int MASTER_SLIDE_ID = 0x00000000; - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; - private byte[] _header; - private static long _type = 1007l; + private byte[] _header; + private static long _type = 1007l; - private int masterID; - private int notesID; + private int masterID; + private int notesID; - private boolean followMasterObjects; - private boolean followMasterScheme; - private boolean followMasterBackground; - private SlideAtomLayout layoutAtom; - private byte[] reserved; + private boolean followMasterObjects; + private boolean followMasterScheme; + private boolean followMasterBackground; + private SlideAtomLayout layoutAtom; + private byte[] reserved; - /** Get the ID of the master slide used. 0 if this is a master slide, otherwise -2147483648 */ - public int getMasterID() { return masterID; } + /** Get the ID of the master slide used. 0 if this is a master slide, otherwise -2147483648 */ + public int getMasterID() { return masterID; } /** Change slide master. */ public void setMasterID(int id) { masterID = id; } - /** Get the ID of the notes for this slide. 0 if doesn't have one */ - public int getNotesID() { return notesID; } - /** Get the embedded SSlideLayoutAtom */ - public SlideAtomLayout getSSlideLayoutAtom() { return layoutAtom; } - - /** Change the ID of the notes for this slide. 0 if it no longer has one */ - public void setNotesID(int id) { notesID = id; } - - public boolean getFollowMasterObjects() { return followMasterObjects; } - public boolean getFollowMasterScheme() { return followMasterScheme; } - public boolean getFollowMasterBackground() { return followMasterBackground; } - public void setFollowMasterObjects(boolean flag) { followMasterObjects = flag; } - public void setFollowMasterScheme(boolean flag) { followMasterScheme = flag; } - public void setFollowMasterBackground(boolean flag) { followMasterBackground = flag; } - - - /* *************** record code follows ********************** */ - - /** - * For the Slide Atom - */ - protected SlideAtom(byte[] source, int start, int len) { - // Sanity Checking - if(len < 30) { len = 30; } - - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Grab the 12 bytes that is "SSlideLayoutAtom" - byte[] SSlideLayoutAtomData = Arrays.copyOfRange(source,start+8, start+12+8); - // Use them to build up the SSlideLayoutAtom - layoutAtom = new SlideAtomLayout(SSlideLayoutAtomData); - - // Get the IDs of the master and notes - masterID = LittleEndian.getInt(source,start+12+8); - notesID = LittleEndian.getInt(source,start+16+8); - - // Grok the flags, stored as bits - int flags = LittleEndian.getUShort(source,start+20+8); - followMasterBackground = (flags & 4) == 4; - followMasterScheme = (flags & 2) == 2; - followMasterObjects = (flags & 1) == 1; - - // If there's any other bits of data, keep them about - // 8 bytes header + 20 bytes to flags + 2 bytes flags = 30 bytes - reserved = IOUtils.safelyClone(source,start+30, len-30, MAX_RECORD_LENGTH); - } - - /** - * Create a new SlideAtom, to go with a new Slide - */ - public SlideAtom(){ - _header = new byte[8]; - LittleEndian.putUShort(_header, 0, 2); - LittleEndian.putUShort(_header, 2, (int)_type); - LittleEndian.putInt(_header, 4, 24); - - byte[] ssdate = new byte[12]; - layoutAtom = new SlideAtomLayout(ssdate); - layoutAtom.setGeometryType(SlideLayoutType.BLANK_SLIDE); - - followMasterObjects = true; - followMasterScheme = true; - followMasterBackground = true; - masterID = USES_MASTER_SLIDE_ID; // -2147483648; - notesID = 0; - reserved = new byte[2]; - } - - /** - * We are of type 1007 - */ - @Override + /** Get the ID of the notes for this slide. 0 if doesn't have one */ + public int getNotesID() { return notesID; } + /** Get the embedded SSlideLayoutAtom */ + public SlideAtomLayout getSSlideLayoutAtom() { return layoutAtom; } + + /** Change the ID of the notes for this slide. 0 if it no longer has one */ + public void setNotesID(int id) { notesID = id; } + + public boolean getFollowMasterObjects() { return followMasterObjects; } + public boolean getFollowMasterScheme() { return followMasterScheme; } + public boolean getFollowMasterBackground() { return followMasterBackground; } + public void setFollowMasterObjects(boolean flag) { followMasterObjects = flag; } + public void setFollowMasterScheme(boolean flag) { followMasterScheme = flag; } + public void setFollowMasterBackground(boolean flag) { followMasterBackground = flag; } + + + /* *************** record code follows ********************** */ + + /** + * For the Slide Atom + */ + protected SlideAtom(byte[] source, int start, int len) { + // Sanity Checking + if(len < 30) { len = 30; } + + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Grab the 12 bytes that is "SSlideLayoutAtom" + byte[] SSlideLayoutAtomData = Arrays.copyOfRange(source,start+8, start+12+8); + // Use them to build up the SSlideLayoutAtom + layoutAtom = new SlideAtomLayout(SSlideLayoutAtomData); + + // Get the IDs of the master and notes + masterID = LittleEndian.getInt(source,start+12+8); + notesID = LittleEndian.getInt(source,start+16+8); + + // Grok the flags, stored as bits + int flags = LittleEndian.getUShort(source,start+20+8); + followMasterBackground = (flags & 4) == 4; + followMasterScheme = (flags & 2) == 2; + followMasterObjects = (flags & 1) == 1; + + // If there's any other bits of data, keep them about + // 8 bytes header + 20 bytes to flags + 2 bytes flags = 30 bytes + reserved = IOUtils.safelyClone(source,start+30, len-30, MAX_RECORD_LENGTH); + } + + /** + * Create a new SlideAtom, to go with a new Slide + */ + public SlideAtom(){ + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 2); + LittleEndian.putUShort(_header, 2, (int)_type); + LittleEndian.putInt(_header, 4, 24); + + byte[] ssdate = new byte[12]; + layoutAtom = new SlideAtomLayout(ssdate); + layoutAtom.setGeometryType(SlideLayoutType.BLANK_SLIDE); + + followMasterObjects = true; + followMasterScheme = true; + followMasterBackground = true; + masterID = USES_MASTER_SLIDE_ID; // -2147483648; + notesID = 0; + reserved = new byte[2]; + } + + /** + * We are of type 1007 + */ + @Override public long getRecordType() { return _type; } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - // Header - out.write(_header); - - // SSSlideLayoutAtom stuff - layoutAtom.writeOut(out); - - // IDs - writeLittleEndian(masterID,out); - writeLittleEndian(notesID,out); - - // Flags - short flags = 0; - if(followMasterObjects) { flags += 1; } - if(followMasterScheme) { flags += 2; } - if(followMasterBackground) { flags += 4; } - writeLittleEndian(flags,out); - - // Reserved data - out.write(reserved); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "masterID", this::getMasterID, - "notesID", this::getNotesID, - "followMasterObjects", this::getFollowMasterObjects, - "followMasterScheme", this::getFollowMasterScheme, - "followMasterBackground", this::getFollowMasterBackground, - "layoutAtom", this::getSSlideLayoutAtom - ); - } + // Header + out.write(_header); + + // SSSlideLayoutAtom stuff + layoutAtom.writeOut(out); + + // IDs + writeLittleEndian(masterID,out); + writeLittleEndian(notesID,out); + + // Flags + short flags = 0; + if(followMasterObjects) { flags += 1; } + if(followMasterScheme) { flags += 2; } + if(followMasterBackground) { flags += 4; } + writeLittleEndian(flags,out); + + // Reserved data + out.write(reserved); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "masterID", this::getMasterID, + "notesID", this::getNotesID, + "followMasterObjects", this::getFollowMasterObjects, + "followMasterScheme", this::getFollowMasterScheme, + "followMasterBackground", this::getFollowMasterBackground, + "layoutAtom", this::getSSlideLayoutAtom + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlideListWithText.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlideListWithText.java index 685e42b4ab..c937edb21b 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlideListWithText.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlideListWithText.java @@ -46,155 +46,155 @@ import org.apache.poi.util.LittleEndian; // For now, pretend to be an atom public final class SlideListWithText extends RecordContainer { - private static final long _type = RecordTypes.SlideListWithText.typeID; - - /** - * Instance filed of the record header indicates that this SlideListWithText stores - * references to slides - */ - public static final int SLIDES = 0; - /** - * Instance filed of the record header indicates that this SlideListWithText stores - * references to master slides - */ - public static final int MASTER = 1; - /** - * Instance filed of the record header indicates that this SlideListWithText stores - * references to notes - */ - public static final int NOTES = 2; - - private final byte[] _header; - - private SlideAtomsSet[] slideAtomsSets; - - /** - * Create a new holder for slide records - */ - protected SlideListWithText(byte[] source, int start, int len) { - // Grab the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Find our children - _children = Record.findChildRecords(source,start+8,len-8); - - // Group our children together into SlideAtomsSets - // That way, model layer code can just grab the sets to use, - // without having to try to match the children together - List<SlideAtomsSet> sets = new ArrayList<>(); - for(int i=0; i<_children.length; i++) { - if(_children[i] instanceof SlidePersistAtom) { - // Find where the next SlidePersistAtom is - int endPos = i+1; - while(endPos < _children.length && !(_children[endPos] instanceof SlidePersistAtom)) { - endPos += 1; - } - - int clen = endPos - i - 1; - - // Create a SlideAtomsSets, not caring if they're empty - //if(emptySet) { continue; } - org.apache.poi.hslf.record.Record[] spaChildren = Arrays.copyOfRange(_children,i+1, i+1+clen, org.apache.poi.hslf.record.Record[].class); - SlideAtomsSet set = new SlideAtomsSet((SlidePersistAtom)_children[i],spaChildren); - sets.add(set); - - // Wind on - i += clen; - } - } - - // Turn the list into an array - slideAtomsSets = sets.toArray(new SlideAtomsSet[0]); - } - - /** - * Create a new, empty, SlideListWithText - */ - public SlideListWithText(){ - _header = new byte[8]; - LittleEndian.putUShort(_header, 0, 15); - LittleEndian.putUShort(_header, 2, (int)_type); - LittleEndian.putInt(_header, 4, 0); - - // We have no children to start with - _children = new org.apache.poi.hslf.record.Record[0]; - slideAtomsSets = new SlideAtomsSet[0]; - } - - /** - * Add a new SlidePersistAtom, to the end of the current list, - * and update the internal list of SlidePersistAtoms - */ - public void addSlidePersistAtom(SlidePersistAtom spa) { - // Add the new SlidePersistAtom at the end - appendChildRecord(spa); - - SlideAtomsSet newSAS = new SlideAtomsSet(spa, new org.apache.poi.hslf.record.Record[0]); - - // Update our SlideAtomsSets with this - SlideAtomsSet[] sas = new SlideAtomsSet[slideAtomsSets.length+1]; - System.arraycopy(slideAtomsSets, 0, sas, 0, slideAtomsSets.length); - sas[sas.length-1] = newSAS; - slideAtomsSets = sas; - } - - public int getInstance(){ - return LittleEndian.getShort(_header, 0) >> 4; - } - - public void setInstance(int inst){ - LittleEndian.putShort(_header, 0, (short)((inst << 4) | 0xF)); - } - - /** - * Get access to the SlideAtomsSets of the children of this record - */ - public SlideAtomsSet[] getSlideAtomsSets() { - return slideAtomsSets; + private static final long _type = RecordTypes.SlideListWithText.typeID; + + /** + * Instance filed of the record header indicates that this SlideListWithText stores + * references to slides + */ + public static final int SLIDES = 0; + /** + * Instance filed of the record header indicates that this SlideListWithText stores + * references to master slides + */ + public static final int MASTER = 1; + /** + * Instance filed of the record header indicates that this SlideListWithText stores + * references to notes + */ + public static final int NOTES = 2; + + private final byte[] _header; + + private SlideAtomsSet[] slideAtomsSets; + + /** + * Create a new holder for slide records + */ + protected SlideListWithText(byte[] source, int start, int len) { + // Grab the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Find our children + _children = Record.findChildRecords(source,start+8,len-8); + + // Group our children together into SlideAtomsSets + // That way, model layer code can just grab the sets to use, + // without having to try to match the children together + List<SlideAtomsSet> sets = new ArrayList<>(); + for(int i=0; i<_children.length; i++) { + if(_children[i] instanceof SlidePersistAtom) { + // Find where the next SlidePersistAtom is + int endPos = i+1; + while(endPos < _children.length && !(_children[endPos] instanceof SlidePersistAtom)) { + endPos += 1; + } + + int clen = endPos - i - 1; + + // Create a SlideAtomsSets, not caring if they're empty + //if(emptySet) { continue; } + org.apache.poi.hslf.record.Record[] spaChildren = Arrays.copyOfRange(_children,i+1, i+1+clen, org.apache.poi.hslf.record.Record[].class); + SlideAtomsSet set = new SlideAtomsSet((SlidePersistAtom)_children[i],spaChildren); + sets.add(set); + + // Wind on + i += clen; + } + } + + // Turn the list into an array + slideAtomsSets = sets.toArray(new SlideAtomsSet[0]); } - /** - * Get access to the SlideAtomsSets of the children of this record - */ - public void setSlideAtomsSets( SlideAtomsSet[] sas ) { - slideAtomsSets = sas.clone(); + /** + * Create a new, empty, SlideListWithText + */ + public SlideListWithText(){ + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 15); + LittleEndian.putUShort(_header, 2, (int)_type); + LittleEndian.putInt(_header, 4, 0); + + // We have no children to start with + _children = new org.apache.poi.hslf.record.Record[0]; + slideAtomsSets = new SlideAtomsSet[0]; } - /** - * Return the value we were given at creation - */ - @Override - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override - public void writeOut(OutputStream out) throws IOException { - writeOut(_header[0],_header[1],_type,_children,out); - } - - /** - * Inner class to wrap up a matching set of records that hold the - * text for a given sheet. Contains the leading SlidePersistAtom, - * and all of the records until the next SlidePersistAtom. This - * includes sets of TextHeaderAtom and TextBytesAtom/TextCharsAtom, - * along with some others. - */ - public static class SlideAtomsSet { - private final SlidePersistAtom slidePersistAtom; - private final org.apache.poi.hslf.record.Record[] slideRecords; - - /** Get the SlidePersistAtom, which gives details on the Slide this text is associated with */ - public SlidePersistAtom getSlidePersistAtom() { return slidePersistAtom; } - /** Get the Text related records for this slide */ - public org.apache.poi.hslf.record.Record[] getSlideRecords() { return slideRecords; } - - /** Create one to hold the Records for one Slide's text */ - public SlideAtomsSet(SlidePersistAtom s, org.apache.poi.hslf.record.Record[] r) { - slidePersistAtom = s; - slideRecords = r.clone(); - } - } + /** + * Add a new SlidePersistAtom, to the end of the current list, + * and update the internal list of SlidePersistAtoms + */ + public void addSlidePersistAtom(SlidePersistAtom spa) { + // Add the new SlidePersistAtom at the end + appendChildRecord(spa); + + SlideAtomsSet newSAS = new SlideAtomsSet(spa, new org.apache.poi.hslf.record.Record[0]); + + // Update our SlideAtomsSets with this + SlideAtomsSet[] sas = new SlideAtomsSet[slideAtomsSets.length+1]; + System.arraycopy(slideAtomsSets, 0, sas, 0, slideAtomsSets.length); + sas[sas.length-1] = newSAS; + slideAtomsSets = sas; + } + + public int getInstance(){ + return LittleEndian.getShort(_header, 0) >> 4; + } + + public void setInstance(int inst){ + LittleEndian.putShort(_header, 0, (short)((inst << 4) | 0xF)); + } + + /** + * Get access to the SlideAtomsSets of the children of this record + */ + public SlideAtomsSet[] getSlideAtomsSets() { + return slideAtomsSets; + } + + /** + * Get access to the SlideAtomsSets of the children of this record + */ + public void setSlideAtomsSets( SlideAtomsSet[] sas ) { + slideAtomsSets = sas.clone(); + } + + /** + * Return the value we were given at creation + */ + @Override + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override + public void writeOut(OutputStream out) throws IOException { + writeOut(_header[0],_header[1],_type,_children,out); + } + + /** + * Inner class to wrap up a matching set of records that hold the + * text for a given sheet. Contains the leading SlidePersistAtom, + * and all of the records until the next SlidePersistAtom. This + * includes sets of TextHeaderAtom and TextBytesAtom/TextCharsAtom, + * along with some others. + */ + public static class SlideAtomsSet { + private final SlidePersistAtom slidePersistAtom; + private final org.apache.poi.hslf.record.Record[] slideRecords; + + /** Get the SlidePersistAtom, which gives details on the Slide this text is associated with */ + public SlidePersistAtom getSlidePersistAtom() { return slidePersistAtom; } + /** Get the Text related records for this slide */ + public org.apache.poi.hslf.record.Record[] getSlideRecords() { return slideRecords; } + + /** Create one to hold the Records for one Slide's text */ + public SlideAtomsSet(SlidePersistAtom s, org.apache.poi.hslf.record.Record[] r) { + slidePersistAtom = s; + slideRecords = r.clone(); + } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlidePersistAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlidePersistAtom.java index d52552ab7b..b6ea7c93e2 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlidePersistAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/SlidePersistAtom.java @@ -35,123 +35,123 @@ import org.apache.poi.util.LittleEndian; */ public final class SlidePersistAtom extends RecordAtom { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 32; - - private static final long _type = 1011l; - private static final int HAS_SHAPES_OTHER_THAN_PLACEHOLDERS = 4; - - private static final int[] FLAGS_MASKS = { HAS_SHAPES_OTHER_THAN_PLACEHOLDERS }; - private static final String[] FLAGS_NAMES = { "HAS_SHAPES_OTHER_THAN_PLACEHOLDERS" }; - - - private final byte[] _header; - - /** Slide reference ID. Should correspond to the PersistPtr "sheet ID" of the matching slide/notes record */ - private int refID; - private int flags; - - /** Number of placeholder texts that will follow in the SlideListWithText */ - private int numPlaceholderTexts; - /** The internal identifier (256+), which is used to tie slides and notes together */ - private int slideIdentifier; - /** Reserved fields. Who knows what they do */ - private byte[] reservedFields; - - public int getRefID() { - return refID; - } - - public int getSlideIdentifier() { - return slideIdentifier; - } - - public int getNumPlaceholderTexts() { - return numPlaceholderTexts; - } - - public boolean getHasShapesOtherThanPlaceholders() { - return (flags & HAS_SHAPES_OTHER_THAN_PLACEHOLDERS) != 0; - } - - // Only set these if you know what you're doing! - public void setRefID(int id) { - refID = id; - } - public void setSlideIdentifier(int id) { - slideIdentifier = id; - } - - /* *************** record code follows ********************** */ - - /** - * For the SlidePersist Atom - */ - protected SlidePersistAtom(byte[] source, int start, int len) { - // Sanity Checking - if(len < 8) { len = 8; } - - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Grab the reference ID - refID = LittleEndian.getInt(source,start+8); - - // Next up is a set of flags, but only bit 3 is used! - flags = LittleEndian.getInt(source,start+12); - - // Now the number of Placeholder Texts - numPlaceholderTexts = LittleEndian.getInt(source,start+16); - - // Last useful one is the unique slide identifier - slideIdentifier = LittleEndian.getInt(source,start+20); - - // Finally you have typically 4 or 8 bytes of reserved fields, - // all zero running from 24 bytes in to the end - reservedFields = IOUtils.safelyClone(source,start+24, len-24, MAX_RECORD_LENGTH); - } - - /** - * Create a new SlidePersistAtom, for use with a new Slide - */ - public SlidePersistAtom() { - _header = new byte[8]; - LittleEndian.putUShort(_header, 0, 0); - LittleEndian.putUShort(_header, 2, (int)_type); - LittleEndian.putInt(_header, 4, 20); - - flags = HAS_SHAPES_OTHER_THAN_PLACEHOLDERS; - reservedFields = new byte[4]; - } - - /** - * We are of type 1011 - */ - public long getRecordType() { return _type; } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - // Header - size or type unchanged - out.write(_header); - - // Write out our fields - writeLittleEndian(refID,out); - writeLittleEndian(flags,out); - writeLittleEndian(numPlaceholderTexts,out); - writeLittleEndian(slideIdentifier,out); - out.write(reservedFields); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "refID", this::getRefID, - "flags", getBitsAsString(() -> flags, FLAGS_MASKS, FLAGS_NAMES), - "numPlaceholderTexts", this::getNumPlaceholderTexts, - "slideIdentifier", this::getSlideIdentifier - ); - } + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 32; + + private static final long _type = 1011l; + private static final int HAS_SHAPES_OTHER_THAN_PLACEHOLDERS = 4; + + private static final int[] FLAGS_MASKS = { HAS_SHAPES_OTHER_THAN_PLACEHOLDERS }; + private static final String[] FLAGS_NAMES = { "HAS_SHAPES_OTHER_THAN_PLACEHOLDERS" }; + + + private final byte[] _header; + + /** Slide reference ID. Should correspond to the PersistPtr "sheet ID" of the matching slide/notes record */ + private int refID; + private int flags; + + /** Number of placeholder texts that will follow in the SlideListWithText */ + private int numPlaceholderTexts; + /** The internal identifier (256+), which is used to tie slides and notes together */ + private int slideIdentifier; + /** Reserved fields. Who knows what they do */ + private byte[] reservedFields; + + public int getRefID() { + return refID; + } + + public int getSlideIdentifier() { + return slideIdentifier; + } + + public int getNumPlaceholderTexts() { + return numPlaceholderTexts; + } + + public boolean getHasShapesOtherThanPlaceholders() { + return (flags & HAS_SHAPES_OTHER_THAN_PLACEHOLDERS) != 0; + } + + // Only set these if you know what you're doing! + public void setRefID(int id) { + refID = id; + } + public void setSlideIdentifier(int id) { + slideIdentifier = id; + } + + /* *************** record code follows ********************** */ + + /** + * For the SlidePersist Atom + */ + protected SlidePersistAtom(byte[] source, int start, int len) { + // Sanity Checking + if(len < 8) { len = 8; } + + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Grab the reference ID + refID = LittleEndian.getInt(source,start+8); + + // Next up is a set of flags, but only bit 3 is used! + flags = LittleEndian.getInt(source,start+12); + + // Now the number of Placeholder Texts + numPlaceholderTexts = LittleEndian.getInt(source,start+16); + + // Last useful one is the unique slide identifier + slideIdentifier = LittleEndian.getInt(source,start+20); + + // Finally you have typically 4 or 8 bytes of reserved fields, + // all zero running from 24 bytes in to the end + reservedFields = IOUtils.safelyClone(source,start+24, len-24, MAX_RECORD_LENGTH); + } + + /** + * Create a new SlidePersistAtom, for use with a new Slide + */ + public SlidePersistAtom() { + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 0); + LittleEndian.putUShort(_header, 2, (int)_type); + LittleEndian.putInt(_header, 4, 20); + + flags = HAS_SHAPES_OTHER_THAN_PLACEHOLDERS; + reservedFields = new byte[4]; + } + + /** + * We are of type 1011 + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + // Header - size or type unchanged + out.write(_header); + + // Write out our fields + writeLittleEndian(refID,out); + writeLittleEndian(flags,out); + writeLittleEndian(numPlaceholderTexts,out); + writeLittleEndian(slideIdentifier,out); + out.write(reservedFields); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "refID", this::getRefID, + "flags", getBitsAsString(() -> flags, FLAGS_MASKS, FLAGS_NAMES), + "numPlaceholderTexts", this::getNumPlaceholderTexts, + "slideIdentifier", this::getSlideIdentifier + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextBytesAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextBytesAtom.java index 81a503b95c..341693db9b 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextBytesAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextBytesAtom.java @@ -38,88 +38,88 @@ import org.apache.poi.util.StringUtil; public final class TextBytesAtom extends RecordAtom { public static final long _type = RecordTypes.TextBytesAtom.typeID; - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; - - private byte[] _header; - - /** The bytes that make up the text */ - private byte[] _text; - - /** Grabs the text. Uses the default codepage */ - public String getText() { - return StringUtil.getFromCompressedUnicode(_text,0,_text.length); - } - - /** Updates the text in the Atom. Must be 8 bit ascii */ - public void setText(byte[] b) { - // Set the text - _text = b.clone(); - - // Update the size (header bytes 5-8) - LittleEndian.putInt(_header,4,_text.length); - } - - /* *************** record code follows ********************** */ - - /** - * For the TextBytes Atom - */ - protected TextBytesAtom(byte[] source, int start, int len) { - // Sanity Checking - if(len < 8) { len = 8; } - - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Grab the text - _text = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); - } - - /** - * Create an empty TextBytes Atom - */ - public TextBytesAtom() { - _header = new byte[8]; - LittleEndian.putUShort(_header, 0, 0); - LittleEndian.putUShort(_header, 2, (int)_type); - LittleEndian.putInt(_header, 4, 0); - - _text = new byte[]{}; - } - - /** - * We are of type 4008 - */ - @Override + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + + private byte[] _header; + + /** The bytes that make up the text */ + private byte[] _text; + + /** Grabs the text. Uses the default codepage */ + public String getText() { + return StringUtil.getFromCompressedUnicode(_text,0,_text.length); + } + + /** Updates the text in the Atom. Must be 8 bit ascii */ + public void setText(byte[] b) { + // Set the text + _text = b.clone(); + + // Update the size (header bytes 5-8) + LittleEndian.putInt(_header,4,_text.length); + } + + /* *************** record code follows ********************** */ + + /** + * For the TextBytes Atom + */ + protected TextBytesAtom(byte[] source, int start, int len) { + // Sanity Checking + if(len < 8) { len = 8; } + + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Grab the text + _text = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); + } + + /** + * Create an empty TextBytes Atom + */ + public TextBytesAtom() { + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 0); + LittleEndian.putUShort(_header, 2, (int)_type); + LittleEndian.putInt(_header, 4, 0); + + _text = new byte[]{}; + } + + /** + * We are of type 4008 + */ + @Override public long getRecordType() { return _type; } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - // Header - size or type unchanged - out.write(_header); - - // Write out our text - out.write(_text); - } - - /** - * dump debug info; use getText() to return a string - * representation of the atom - */ - @Override + // Header - size or type unchanged + out.write(_header); + + // Write out our text + out.write(_text); + } + + /** + * dump debug info; use getText() to return a string + * representation of the atom + */ + @Override public String toString() { - return GenericRecordJsonWriter.marshal(this); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "text", this::getText - ); - } + return GenericRecordJsonWriter.marshal(this); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "text", this::getText + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextCharsAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextCharsAtom.java index 768aaba6ef..4fd297387d 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextCharsAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextCharsAtom.java @@ -36,86 +36,86 @@ import org.apache.poi.util.StringUtil; public final class TextCharsAtom extends RecordAtom { public static final long _type = RecordTypes.TextCharsAtom.typeID; - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 1_000_000; - - private byte[] _header; - - /** The bytes that make up the text */ - private byte[] _text; - - /** Grabs the text. */ - public String getText() { - return StringUtil.getFromUnicodeLE(_text); - } - - /** Updates the text in the Atom. */ - public void setText(String text) { - // Convert to little endian unicode - _text = IOUtils.safelyAllocate(text.length() * 2L, MAX_RECORD_LENGTH); - StringUtil.putUnicodeLE(text,_text,0); - - // Update the size (header bytes 5-8) - LittleEndian.putInt(_header,4,_text.length); - } - - /* *************** record code follows ********************** */ - - /** - * For the TextChars Atom - */ - protected TextCharsAtom(byte[] source, int start, int len) { - // Sanity Checking - if(len < 8) { len = 8; } - - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Grab the text - _text = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); - } - /** - * Create an empty TextCharsAtom - */ - public TextCharsAtom() { - // 0 length header - _header = new byte[] { 0, 0, 0xA0-256, 0x0f, 0, 0, 0, 0 }; - // Empty text - _text = new byte[0]; - } - - /** - * We are of type 4000 - */ - @Override + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + + private byte[] _header; + + /** The bytes that make up the text */ + private byte[] _text; + + /** Grabs the text. */ + public String getText() { + return StringUtil.getFromUnicodeLE(_text); + } + + /** Updates the text in the Atom. */ + public void setText(String text) { + // Convert to little endian unicode + _text = IOUtils.safelyAllocate(text.length() * 2L, MAX_RECORD_LENGTH); + StringUtil.putUnicodeLE(text,_text,0); + + // Update the size (header bytes 5-8) + LittleEndian.putInt(_header,4,_text.length); + } + + /* *************** record code follows ********************** */ + + /** + * For the TextChars Atom + */ + protected TextCharsAtom(byte[] source, int start, int len) { + // Sanity Checking + if(len < 8) { len = 8; } + + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Grab the text + _text = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH); + } + /** + * Create an empty TextCharsAtom + */ + public TextCharsAtom() { + // 0 length header + _header = new byte[] { 0, 0, 0xA0-256, 0x0f, 0, 0, 0, 0 }; + // Empty text + _text = new byte[0]; + } + + /** + * We are of type 4000 + */ + @Override public long getRecordType() { return _type; } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - // Header - size or type unchanged - out.write(_header); - - // Write out our text - out.write(_text); - } - - /** - * dump debug info; use getText() to return a string - * representation of the atom - */ - @Override + // Header - size or type unchanged + out.write(_header); + + // Write out our text + out.write(_text); + } + + /** + * dump debug info; use getText() to return a string + * representation of the atom + */ + @Override public String toString() { - return GenericRecordJsonWriter.marshal(this); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "text", this::getText - ); - } + return GenericRecordJsonWriter.marshal(this); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "text", this::getText + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextHeaderAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextHeaderAtom.java index 187e2f4bce..99730fcc12 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextHeaderAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/TextHeaderAtom.java @@ -36,97 +36,97 @@ import org.apache.poi.util.LittleEndian; public final class TextHeaderAtom extends RecordAtom implements ParentAwareRecord { public static final long _type = RecordTypes.TextHeaderAtom.typeID; - private byte[] _header; - private org.apache.poi.hslf.record.RecordContainer parentRecord; + private byte[] _header; + private org.apache.poi.hslf.record.RecordContainer parentRecord; - /** The kind of text it is */ - private int textType; - /** position in the owning SlideListWithText */ - private int index = -1; + /** The kind of text it is */ + private int textType; + /** position in the owning SlideListWithText */ + private int index = -1; - public int getTextType() { return textType; } - public void setTextType(int type) { textType = type; } + public int getTextType() { return textType; } + public void setTextType(int type) { textType = type; } - public TextPlaceholder getTextTypeEnum() { - return TextPlaceholder.fromNativeId(textType); - } + public TextPlaceholder getTextTypeEnum() { + return TextPlaceholder.fromNativeId(textType); + } - public void setTextTypeEnum(TextPlaceholder placeholder) { - textType = placeholder.nativeId; - } + public void setTextTypeEnum(TextPlaceholder placeholder) { + textType = placeholder.nativeId; + } /** * @return 0-based index of the text run in the SLWT container */ - public int getIndex() { return index; } + public int getIndex() { return index; } /** * @param index 0-based index of the text run in the SLWT container */ - public void setIndex(int index) { this.index = index; } + public void setIndex(int index) { this.index = index; } - @Override + @Override public org.apache.poi.hslf.record.RecordContainer getParentRecord() { return parentRecord; } - @Override + @Override public void setParentRecord(RecordContainer record) { this.parentRecord = record; } - /* *************** record code follows ********************** */ - - /** - * For the TextHeader Atom - */ - protected TextHeaderAtom(byte[] source, int start, int len) { - // Sanity Checking - we're always 12 bytes long - if(len < 12) { - len = 12; - if(source.length - start < 12) { - throw new HSLFException("Not enough data to form a TextHeaderAtom (always 12 bytes long) - found " + (source.length - start)); - } - } - - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - - // Grab the type - textType = LittleEndian.getInt(source,start+8); - } - - /** - * Create a new TextHeader Atom, for an unknown type of text - */ - public TextHeaderAtom() { - _header = new byte[8]; - LittleEndian.putUShort(_header, 0, 0); - LittleEndian.putUShort(_header, 2, (int)_type); - LittleEndian.putInt(_header, 4, 4); - - textType = TextPlaceholder.OTHER.nativeId; - } - - /** - * We are of type 3999 - */ - @Override + /* *************** record code follows ********************** */ + + /** + * For the TextHeader Atom + */ + protected TextHeaderAtom(byte[] source, int start, int len) { + // Sanity Checking - we're always 12 bytes long + if(len < 12) { + len = 12; + if(source.length - start < 12) { + throw new HSLFException("Not enough data to form a TextHeaderAtom (always 12 bytes long) - found " + (source.length - start)); + } + } + + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + + // Grab the type + textType = LittleEndian.getInt(source,start+8); + } + + /** + * Create a new TextHeader Atom, for an unknown type of text + */ + public TextHeaderAtom() { + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 0); + LittleEndian.putUShort(_header, 2, (int)_type); + LittleEndian.putInt(_header, 4, 4); + + textType = TextPlaceholder.OTHER.nativeId; + } + + /** + * We are of type 3999 + */ + @Override public long getRecordType() { return _type; } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - // Header - size or type unchanged - out.write(_header); - - // Write out our type - writeLittleEndian(textType,out); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "index", this::getIndex, - "textType", this::getTextTypeEnum - ); - } + // Header - size or type unchanged + out.write(_header); + + // Write out our type + writeLittleEndian(textType,out); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "index", this::getIndex, + "textType", this::getTextTypeEnum + ); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/UnknownRecordPlaceholder.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/UnknownRecordPlaceholder.java index 6b1b5483e4..620d600b75 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/UnknownRecordPlaceholder.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/UnknownRecordPlaceholder.java @@ -36,49 +36,49 @@ import org.apache.poi.util.LittleEndian; public final class UnknownRecordPlaceholder extends RecordAtom { - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 20_000_000; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 20_000_000; - private byte[] _contents; - private long _type; + private byte[] _contents; + private long _type; - /** - * Create a new holder for a record we don't grok - */ - protected UnknownRecordPlaceholder(byte[] source, int start, int len) { - // Sanity Checking - including whole header, so treat - // length as based of 0, not 8 (including header size based) - if(len < 0) { len = 0; } + /** + * Create a new holder for a record we don't grok + */ + protected UnknownRecordPlaceholder(byte[] source, int start, int len) { + // Sanity Checking - including whole header, so treat + // length as based of 0, not 8 (including header size based) + if(len < 0) { len = 0; } - // Treat as an atom, grab and hold everything - _contents = IOUtils.safelyClone(source, start, len, MAX_RECORD_LENGTH); - _type = LittleEndian.getUShort(_contents,2); - } + // Treat as an atom, grab and hold everything + _contents = IOUtils.safelyClone(source, start, len, MAX_RECORD_LENGTH); + _type = LittleEndian.getUShort(_contents,2); + } - /** - * Return the value we were given at creation - */ - public long getRecordType() { - return _type; - } + /** + * Return the value we were given at creation + */ + public long getRecordType() { + return _type; + } - /** - * Return the value as enum we were given at creation - */ - public org.apache.poi.hslf.record.RecordTypes getRecordTypeEnum() { - return RecordTypes.forTypeID((int)_type); - } + /** + * Return the value as enum we were given at creation + */ + public org.apache.poi.hslf.record.RecordTypes getRecordTypeEnum() { + return RecordTypes.forTypeID((int)_type); + } - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - out.write(_contents); - } + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_contents); + } - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties("contents", () -> _contents); - } + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties("contents", () -> _contents); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/UserEditAtom.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/UserEditAtom.java index b89da4a98c..898e22dae2 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/UserEditAtom.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/UserEditAtom.java @@ -40,169 +40,169 @@ import org.apache.poi.util.LittleEndianConsts; public final class UserEditAtom extends PositionDependentRecordAtom { - public static final int LAST_VIEW_NONE = 0; - public static final int LAST_VIEW_SLIDE_VIEW = 1; - public static final int LAST_VIEW_OUTLINE_VIEW = 2; - public static final int LAST_VIEW_NOTES = 3; - - private byte[] _header; - private static final long _type = RecordTypes.UserEditAtom.typeID; - private short unused; - - private int lastViewedSlideID; - private int pptVersion; - private int lastUserEditAtomOffset; - private int persistPointersOffset; - private int docPersistRef; - private int maxPersistWritten; - private short lastViewType; - private int encryptSessionPersistIdRef = -1; - - // Somewhat user facing getters - public int getLastViewedSlideID() { return lastViewedSlideID; } - public short getLastViewType() { return lastViewType; } - - // Scary internal getters - public int getLastUserEditAtomOffset() { return lastUserEditAtomOffset; } - public int getPersistPointersOffset() { return persistPointersOffset; } - public int getDocPersistRef() { return docPersistRef; } - public int getMaxPersistWritten() { return maxPersistWritten; } - public int getEncryptSessionPersistIdRef() { return encryptSessionPersistIdRef; } - - // More scary internal setters - public void setLastUserEditAtomOffset(int offset) { lastUserEditAtomOffset = offset; } - public void setPersistPointersOffset(int offset) { persistPointersOffset = offset; } - public void setLastViewType(short type) { lastViewType=type; } + public static final int LAST_VIEW_NONE = 0; + public static final int LAST_VIEW_SLIDE_VIEW = 1; + public static final int LAST_VIEW_OUTLINE_VIEW = 2; + public static final int LAST_VIEW_NOTES = 3; + + private byte[] _header; + private static final long _type = RecordTypes.UserEditAtom.typeID; + private short unused; + + private int lastViewedSlideID; + private int pptVersion; + private int lastUserEditAtomOffset; + private int persistPointersOffset; + private int docPersistRef; + private int maxPersistWritten; + private short lastViewType; + private int encryptSessionPersistIdRef = -1; + + // Somewhat user facing getters + public int getLastViewedSlideID() { return lastViewedSlideID; } + public short getLastViewType() { return lastViewType; } + + // Scary internal getters + public int getLastUserEditAtomOffset() { return lastUserEditAtomOffset; } + public int getPersistPointersOffset() { return persistPointersOffset; } + public int getDocPersistRef() { return docPersistRef; } + public int getMaxPersistWritten() { return maxPersistWritten; } + public int getEncryptSessionPersistIdRef() { return encryptSessionPersistIdRef; } + + // More scary internal setters + public void setLastUserEditAtomOffset(int offset) { lastUserEditAtomOffset = offset; } + public void setPersistPointersOffset(int offset) { persistPointersOffset = offset; } + public void setLastViewType(short type) { lastViewType=type; } public void setMaxPersistWritten(int max) { maxPersistWritten=max; } public void setEncryptSessionPersistIdRef(int id) { encryptSessionPersistIdRef=id; LittleEndian.putInt(_header,4,(id == -1 ? 28 : 32)); } - /* *************** record code follows ********************** */ - - /** - * For the UserEdit Atom - */ - protected UserEditAtom(byte[] source, int start, int len) { - // Sanity Checking - if(len < 34) { len = 34; } - - int offset = start; - // Get the header - _header = Arrays.copyOfRange(source, start, start+8); - offset += 8; - - // Get the last viewed slide ID - lastViewedSlideID = LittleEndian.getInt(source,offset); - offset += LittleEndianConsts.INT_SIZE; - - // Get the PPT version - pptVersion = LittleEndian.getInt(source,offset); - offset += LittleEndianConsts.INT_SIZE; - - // Get the offset to the previous incremental save's UserEditAtom - // This will be the byte offset on disk where the previous one - // starts, or 0 if this is the first one - lastUserEditAtomOffset = LittleEndian.getInt(source,offset); - offset += LittleEndianConsts.INT_SIZE; - - // Get the offset to the persist pointers - // This will be the byte offset on disk where the preceding - // PersistPtrFullBlock or PersistPtrIncrementalBlock starts - persistPointersOffset = LittleEndian.getInt(source,offset); - offset += LittleEndianConsts.INT_SIZE; - - // Get the persist reference for the document persist object - // Normally seems to be 1 - docPersistRef = LittleEndian.getInt(source,offset); - offset += LittleEndianConsts.INT_SIZE; - - // Maximum number of persist objects written - maxPersistWritten = LittleEndian.getInt(source,offset); - offset += LittleEndianConsts.INT_SIZE; - - // Last view type - lastViewType = LittleEndian.getShort(source,offset); - offset += LittleEndianConsts.SHORT_SIZE; - - // unused - unused = LittleEndian.getShort(source,offset); - offset += LittleEndianConsts.SHORT_SIZE; - - // There might be a few more bytes, which are a reserved field - if (offset-start<len) { - encryptSessionPersistIdRef = LittleEndian.getInt(source,offset); - offset += LittleEndianConsts.INT_SIZE; - } - - assert(offset-start == len); - } - - /** - * We are of type 4085 - */ - @Override + /* *************** record code follows ********************** */ + + /** + * For the UserEdit Atom + */ + protected UserEditAtom(byte[] source, int start, int len) { + // Sanity Checking + if(len < 34) { len = 34; } + + int offset = start; + // Get the header + _header = Arrays.copyOfRange(source, start, start+8); + offset += 8; + + // Get the last viewed slide ID + lastViewedSlideID = LittleEndian.getInt(source,offset); + offset += LittleEndianConsts.INT_SIZE; + + // Get the PPT version + pptVersion = LittleEndian.getInt(source,offset); + offset += LittleEndianConsts.INT_SIZE; + + // Get the offset to the previous incremental save's UserEditAtom + // This will be the byte offset on disk where the previous one + // starts, or 0 if this is the first one + lastUserEditAtomOffset = LittleEndian.getInt(source,offset); + offset += LittleEndianConsts.INT_SIZE; + + // Get the offset to the persist pointers + // This will be the byte offset on disk where the preceding + // PersistPtrFullBlock or PersistPtrIncrementalBlock starts + persistPointersOffset = LittleEndian.getInt(source,offset); + offset += LittleEndianConsts.INT_SIZE; + + // Get the persist reference for the document persist object + // Normally seems to be 1 + docPersistRef = LittleEndian.getInt(source,offset); + offset += LittleEndianConsts.INT_SIZE; + + // Maximum number of persist objects written + maxPersistWritten = LittleEndian.getInt(source,offset); + offset += LittleEndianConsts.INT_SIZE; + + // Last view type + lastViewType = LittleEndian.getShort(source,offset); + offset += LittleEndianConsts.SHORT_SIZE; + + // unused + unused = LittleEndian.getShort(source,offset); + offset += LittleEndianConsts.SHORT_SIZE; + + // There might be a few more bytes, which are a reserved field + if (offset-start<len) { + encryptSessionPersistIdRef = LittleEndian.getInt(source,offset); + offset += LittleEndianConsts.INT_SIZE; + } + + assert(offset-start == len); + } + + /** + * We are of type 4085 + */ + @Override public long getRecordType() { return _type; } - /** - * At write-out time, update the references to PersistPtrs and - * other UserEditAtoms to point to their new positions - */ - @Override + /** + * At write-out time, update the references to PersistPtrs and + * other UserEditAtoms to point to their new positions + */ + @Override public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup) { - // Look up the new positions of our preceding UserEditAtomOffset - if(lastUserEditAtomOffset != 0) { - Integer newLocation = oldToNewReferencesLookup.get(Integer.valueOf(lastUserEditAtomOffset)); - if(newLocation == null) { - throw new HSLFException("Couldn't find the new location of the UserEditAtom that used to be at " + lastUserEditAtomOffset); - } - lastUserEditAtomOffset = newLocation.intValue(); - } - - // Ditto for our PersistPtr - Integer newLocation = oldToNewReferencesLookup.get(Integer.valueOf(persistPointersOffset)); - if(newLocation == null) { - throw new HSLFException("Couldn't find the new location of the PersistPtr that used to be at " + persistPointersOffset); - } - persistPointersOffset = newLocation.intValue(); - } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - @Override + // Look up the new positions of our preceding UserEditAtomOffset + if(lastUserEditAtomOffset != 0) { + Integer newLocation = oldToNewReferencesLookup.get(Integer.valueOf(lastUserEditAtomOffset)); + if(newLocation == null) { + throw new HSLFException("Couldn't find the new location of the UserEditAtom that used to be at " + lastUserEditAtomOffset); + } + lastUserEditAtomOffset = newLocation.intValue(); + } + + // Ditto for our PersistPtr + Integer newLocation = oldToNewReferencesLookup.get(Integer.valueOf(persistPointersOffset)); + if(newLocation == null) { + throw new HSLFException("Couldn't find the new location of the PersistPtr that used to be at " + persistPointersOffset); + } + persistPointersOffset = newLocation.intValue(); + } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + @Override public void writeOut(OutputStream out) throws IOException { - // Header - out.write(_header); - - // Write out the values - writeLittleEndian(lastViewedSlideID,out); - writeLittleEndian(pptVersion,out); - writeLittleEndian(lastUserEditAtomOffset,out); - writeLittleEndian(persistPointersOffset,out); - writeLittleEndian(docPersistRef,out); - writeLittleEndian(maxPersistWritten,out); - writeLittleEndian(lastViewType,out); - writeLittleEndian(unused,out); - if (encryptSessionPersistIdRef != -1) { - // optional field - writeLittleEndian(encryptSessionPersistIdRef,out); - } - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - final Map<String, Supplier<?>> m = new LinkedHashMap<>(); - m.put("lastViewedSlideID", this::getLastViewedSlideID); - m.put("pptVersion", () -> pptVersion); - m.put("lastUserEditAtomOffset", this::getLastUserEditAtomOffset); - m.put("persistPointersOffset", this::getPersistPointersOffset); - m.put("docPersistRef", this::getDocPersistRef); - m.put("maxPersistWritten", this::getMaxPersistWritten); - m.put("lastViewType", this::getLastViewType); - m.put("encryptSessionPersistIdRef", this::getEncryptSessionPersistIdRef); - return Collections.unmodifiableMap(m); - } + // Header + out.write(_header); + + // Write out the values + writeLittleEndian(lastViewedSlideID,out); + writeLittleEndian(pptVersion,out); + writeLittleEndian(lastUserEditAtomOffset,out); + writeLittleEndian(persistPointersOffset,out); + writeLittleEndian(docPersistRef,out); + writeLittleEndian(maxPersistWritten,out); + writeLittleEndian(lastViewType,out); + writeLittleEndian(unused,out); + if (encryptSessionPersistIdRef != -1) { + // optional field + writeLittleEndian(encryptSessionPersistIdRef,out); + } + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + final Map<String, Supplier<?>> m = new LinkedHashMap<>(); + m.put("lastViewedSlideID", this::getLastViewedSlideID); + m.put("pptVersion", () -> pptVersion); + m.put("lastUserEditAtomOffset", this::getLastUserEditAtomOffset); + m.put("persistPointersOffset", this::getPersistPointersOffset); + m.put("docPersistRef", this::getDocPersistRef); + m.put("maxPersistWritten", this::getMaxPersistWritten); + m.put("lastViewType", this::getLastViewType); + m.put("encryptSessionPersistIdRef", this::getEncryptSessionPersistIdRef); + return Collections.unmodifiableMap(m); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFObjectShape.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFObjectShape.java index a5414672b9..2111d5387a 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFObjectShape.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFObjectShape.java @@ -97,14 +97,14 @@ public final class HSLFObjectShape extends HSLFPictureShape implements ObjectSha * @param objectId the unique identifier for the OLE object */ public void setObjectID(int objectId){ - setEscherProperty(EscherPropertyTypes.BLIP__PICTUREID, objectId); + setEscherProperty(EscherPropertyTypes.BLIP__PICTUREID, objectId); - EscherContainerRecord ecr = getSpContainer(); - EscherSpRecord spRecord = ecr.getChildById(EscherSpRecord.RECORD_ID); - if (spRecord != null) { + EscherContainerRecord ecr = getSpContainer(); + EscherSpRecord spRecord = ecr.getChildById(EscherSpRecord.RECORD_ID); + if (spRecord != null) { spRecord.setFlags(spRecord.getFlags() | EscherSpRecord.FLAG_OLESHAPE); } else { - LOG.atWarn().log("Ole shape record not found."); + LOG.atWarn().log("Ole shape record not found."); } HSLFEscherClientDataRecord cldata = getClientData(true); @@ -116,8 +116,8 @@ public final class HSLFObjectShape extends HSLFPictureShape implements ObjectSha } } if (uer == null) { - uer = new ExObjRefAtom(); - cldata.addChild(uer); + uer = new ExObjRefAtom(); + cldata.addChild(uer); } uer.setExObjIdRef(objectId); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlide.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlide.java index 1d51de9f91..d63ea39721 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlide.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlide.java @@ -56,56 +56,56 @@ import org.apache.poi.sl.usermodel.TextShape.TextPlaceholder; */ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTextParagraph> { - private int _slideNo; - private SlideAtomsSet _atomSet; - private final List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<>(); - private HSLFNotes _notes; // usermodel needs to set this - - /** - * Constructs a Slide from the Slide record, and the SlideAtomsSet - * containing the text. - * Initializes TextRuns, to provide easier access to the text - * - * @param slide the Slide record we're based on - * @param notes the Notes sheet attached to us - * @param atomSet the SlideAtomsSet to get the text from - */ - public HSLFSlide(org.apache.poi.hslf.record.Slide slide, HSLFNotes notes, SlideAtomsSet atomSet, int slideIdentifier, int slideNumber) { + private int _slideNo; + private SlideAtomsSet _atomSet; + private final List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<>(); + private HSLFNotes _notes; // usermodel needs to set this + + /** + * Constructs a Slide from the Slide record, and the SlideAtomsSet + * containing the text. + * Initializes TextRuns, to provide easier access to the text + * + * @param slide the Slide record we're based on + * @param notes the Notes sheet attached to us + * @param atomSet the SlideAtomsSet to get the text from + */ + public HSLFSlide(org.apache.poi.hslf.record.Slide slide, HSLFNotes notes, SlideAtomsSet atomSet, int slideIdentifier, int slideNumber) { super(slide, slideIdentifier); - _notes = notes; - _atomSet = atomSet; - _slideNo = slideNumber; - - // For the text coming in from the SlideAtomsSet: - // Build up TextRuns from pairs of TextHeaderAtom and - // one of TextBytesAtom or TextCharsAtom - if (_atomSet != null && _atomSet.getSlideRecords().length > 0) { - // Grab text from SlideListWithTexts entries - _paragraphs.addAll(HSLFTextParagraph.findTextParagraphs(_atomSet.getSlideRecords())); - if (_paragraphs.isEmpty()) { - throw new HSLFException("No text records found for slide"); - } - } - - // Grab text from slide's PPDrawing - for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) { - if (!_paragraphs.contains(l)) { + _notes = notes; + _atomSet = atomSet; + _slideNo = slideNumber; + + // For the text coming in from the SlideAtomsSet: + // Build up TextRuns from pairs of TextHeaderAtom and + // one of TextBytesAtom or TextCharsAtom + if (_atomSet != null && _atomSet.getSlideRecords().length > 0) { + // Grab text from SlideListWithTexts entries + _paragraphs.addAll(HSLFTextParagraph.findTextParagraphs(_atomSet.getSlideRecords())); + if (_paragraphs.isEmpty()) { + throw new HSLFException("No text records found for slide"); + } + } + + // Grab text from slide's PPDrawing + for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) { + if (!_paragraphs.contains(l)) { _paragraphs.add(l); } - } - } - - /** - * Create a new Slide instance - * @param sheetNumber The internal number of the sheet, as used by PersistPtrHolder - * @param slideNumber The user facing number of the sheet - */ - public HSLFSlide(int sheetNumber, int sheetRefId, int slideNumber){ - super(new org.apache.poi.hslf.record.Slide(), sheetNumber); - _slideNo = slideNumber; + } + } + + /** + * Create a new Slide instance + * @param sheetNumber The internal number of the sheet, as used by PersistPtrHolder + * @param slideNumber The user facing number of the sheet + */ + public HSLFSlide(int sheetNumber, int sheetRefId, int slideNumber){ + super(new org.apache.poi.hslf.record.Slide(), sheetNumber); + _slideNo = slideNumber; getSheetContainer().setSheetId(sheetRefId); - } + } /** * Returns the Notes Sheet for this slide, or null if there isn't one @@ -115,36 +115,36 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe return _notes; } - /** - * Sets the Notes that are associated with this. Updates the - * references in the records to point to the new ID - */ - @Override - public void setNotes(Notes<HSLFShape,HSLFTextParagraph> notes) { + /** + * Sets the Notes that are associated with this. Updates the + * references in the records to point to the new ID + */ + @Override + public void setNotes(Notes<HSLFShape,HSLFTextParagraph> notes) { if (notes != null && !(notes instanceof HSLFNotes)) { throw new IllegalArgumentException("notes needs to be of type HSLFNotes"); } - _notes = (HSLFNotes)notes; - - // Update the Slide Atom's ID of where to point to - SlideAtom sa = getSlideRecord().getSlideAtom(); - - if(_notes == null) { - // Set to 0 - sa.setNotesID(0); - } else { - // Set to the value from the notes' sheet id - sa.setNotesID(_notes._getSheetNumber()); - } - } - - /** - * Changes the Slide's (external facing) page number. - * @see org.apache.poi.hslf.usermodel.HSLFSlideShow#reorderSlide(int, int) - */ - public void setSlideNumber(int newSlideNumber) { - _slideNo = newSlideNumber; - } + _notes = (HSLFNotes)notes; + + // Update the Slide Atom's ID of where to point to + SlideAtom sa = getSlideRecord().getSlideAtom(); + + if(_notes == null) { + // Set to 0 + sa.setNotesID(0); + } else { + // Set to the value from the notes' sheet id + sa.setNotesID(_notes._getSheetNumber()); + } + } + + /** + * Changes the Slide's (external facing) page number. + * @see org.apache.poi.hslf.usermodel.HSLFSlideShow#reorderSlide(int, int) + */ + public void setSlideNumber(int newSlideNumber) { + _slideNo = newSlideNumber; + } /** * Called by SlideShow ater a new slide is created. @@ -187,79 +187,79 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe dg.setNumShapes(1); } - /** - * Create a {@code TextBox} object that represents the slide's title. - * - * @return {@code TextBox} object that represents the slide's title. - */ - public HSLFTextBox addTitle() { - HSLFPlaceholder pl = new HSLFPlaceholder(); - pl.setShapeType(ShapeType.RECT); - pl.setPlaceholder(Placeholder.TITLE); - pl.setRunType(TextPlaceholder.TITLE.nativeId); - pl.setText("Click to edit title"); - pl.setAnchor(new java.awt.Rectangle(54, 48, 612, 90)); - addShape(pl); - return pl; - } - - - // Complex Accesser methods follow - - /** - * <p> - * The title is a run of text of type {@code TextHeaderAtom.CENTER_TITLE_TYPE} or - * {@code TextHeaderAtom.TITLE_TYPE} - * </p> - * - * @see TextHeaderAtom - */ - @Override - public String getTitle(){ - for (List<HSLFTextParagraph> tp : getTextParagraphs()) { - if (tp.isEmpty()) { + /** + * Create a {@code TextBox} object that represents the slide's title. + * + * @return {@code TextBox} object that represents the slide's title. + */ + public HSLFTextBox addTitle() { + HSLFPlaceholder pl = new HSLFPlaceholder(); + pl.setShapeType(ShapeType.RECT); + pl.setPlaceholder(Placeholder.TITLE); + pl.setRunType(TextPlaceholder.TITLE.nativeId); + pl.setText("Click to edit title"); + pl.setAnchor(new java.awt.Rectangle(54, 48, 612, 90)); + addShape(pl); + return pl; + } + + + // Complex Accesser methods follow + + /** + * <p> + * The title is a run of text of type {@code TextHeaderAtom.CENTER_TITLE_TYPE} or + * {@code TextHeaderAtom.TITLE_TYPE} + * </p> + * + * @see TextHeaderAtom + */ + @Override + public String getTitle(){ + for (List<HSLFTextParagraph> tp : getTextParagraphs()) { + if (tp.isEmpty()) { continue; } - int type = tp.get(0).getRunType(); - if (TextPlaceholder.isTitle(type)) { + int type = tp.get(0).getRunType(); + if (TextPlaceholder.isTitle(type)) { String str = HSLFTextParagraph.getRawText(tp); return HSLFTextParagraph.toExternalString(str, type); } - } - return null; - } + } + return null; + } @Override - public String getSlideName() { + public String getSlideName() { final CString name = (CString)getSlideRecord().findFirstOfType(RecordTypes.CString.typeID); return name != null ? name.getText() : "Slide"+getSlideNumber(); } - /** - * Returns an array of all the TextRuns found - */ - @Override + /** + * Returns an array of all the TextRuns found + */ + @Override public List<List<HSLFTextParagraph>> getTextParagraphs() { return _paragraphs; } - /** - * Returns the (public facing) page number of this slide - */ - @Override - public int getSlideNumber() { return _slideNo; } + /** + * Returns the (public facing) page number of this slide + */ + @Override + public int getSlideNumber() { return _slideNo; } - /** - * Returns the underlying slide record - */ - public org.apache.poi.hslf.record.Slide getSlideRecord() { + /** + * Returns the underlying slide record + */ + public org.apache.poi.hslf.record.Slide getSlideRecord() { return (org.apache.poi.hslf.record.Slide)getSheetContainer(); } - /** - * @return set of records inside {@code SlideListWithtext} container - * which hold text data for this slide (typically for placeholders). - */ - protected SlideAtomsSet getSlideAtomsSet() { return _atomSet; } + /** + * @return set of records inside {@code SlideListWithtext} container + * which hold text data for this slide (typically for placeholders). + */ + protected SlideAtomsSet getSlideAtomsSet() { return _atomSet; } /** * Returns master sheet associated with this slide. @@ -403,8 +403,8 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe @Override public List<HSLFComment> getComments() { final List<HSLFComment> comments = new ArrayList<>(); - // If there are any, they're in - // ProgTags -> ProgBinaryTag -> BinaryTagData + // If there are any, they're in + // ProgTags -> ProgBinaryTag -> BinaryTagData final RecordContainer binaryTags = selectContainer(getSheetContainer(), 0, RecordTypes.ProgTags, RecordTypes.ProgBinaryTag, RecordTypes.BinaryTagData); @@ -417,7 +417,7 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe } } - return comments; + return comments; } /** @@ -438,33 +438,33 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe /** This will return an atom per TextBox, so if the page has two text boxes the method should return two atoms. */ public StyleTextProp9Atom[] getNumberedListInfo() { - return this.getPPDrawing().getNumberedListInfo(); + return this.getPPDrawing().getNumberedListInfo(); } - public EscherTextboxWrapper[] getTextboxWrappers() { - return this.getPPDrawing().getTextboxWrappers(); - } - - @Override - public void setHidden(boolean hidden) { - org.apache.poi.hslf.record.Slide cont = getSlideRecord(); + public EscherTextboxWrapper[] getTextboxWrappers() { + return this.getPPDrawing().getTextboxWrappers(); + } - SSSlideInfoAtom slideInfo = - (SSSlideInfoAtom)cont.findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID); - if (slideInfo == null) { - slideInfo = new SSSlideInfoAtom(); - cont.addChildAfter(slideInfo, cont.findFirstOfType(RecordTypes.SlideAtom.typeID)); - } + @Override + public void setHidden(boolean hidden) { + org.apache.poi.hslf.record.Slide cont = getSlideRecord(); + + SSSlideInfoAtom slideInfo = + (SSSlideInfoAtom)cont.findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID); + if (slideInfo == null) { + slideInfo = new SSSlideInfoAtom(); + cont.addChildAfter(slideInfo, cont.findFirstOfType(RecordTypes.SlideAtom.typeID)); + } - slideInfo.setEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT, hidden); - } + slideInfo.setEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT, hidden); + } @Override - public boolean isHidden() { - SSSlideInfoAtom slideInfo = - (SSSlideInfoAtom)getSlideRecord().findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID); - return (slideInfo != null) && slideInfo.getEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT); - } + public boolean isHidden() { + SSSlideInfoAtom slideInfo = + (SSSlideInfoAtom)getSlideRecord().findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID); + return (slideInfo != null) && slideInfo.getEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT); + } @Override public void draw(Graphics2D graphics) { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java index e2a3b51155..9975f3c9d4 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java @@ -76,87 +76,87 @@ import org.apache.poi.util.Units; */ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFShape,HSLFTextParagraph>, Closeable, GenericRecord { - /** Powerpoint document entry/stream name */ - public static final String POWERPOINT_DOCUMENT = "PowerPoint Document"; - public static final String PP97_DOCUMENT = "PP97_DUALSTORAGE"; - public static final String PP95_DOCUMENT = "PP40"; + /** Powerpoint document entry/stream name */ + public static final String POWERPOINT_DOCUMENT = "PowerPoint Document"; + public static final String PP97_DOCUMENT = "PP97_DUALSTORAGE"; + public static final String PP95_DOCUMENT = "PP40"; - // For logging - private static final Logger LOG = LogManager.getLogger(HSLFSlideShow.class); + // For logging + private static final Logger LOG = LogManager.getLogger(HSLFSlideShow.class); - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 10_000_000; + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 10_000_000; enum LoadSavePhase { INIT, LOADED - } + } private static final ThreadLocal<LoadSavePhase> loadSavePhase = new ThreadLocal<>(); // What we're based on - private final HSLFSlideShowImpl _hslfSlideShow; - - // 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 Map<Integer,Integer> _sheetIdToCoreRecordsLookup; - - // Records that are interesting - private Document _documentRecord; - - // Friendly objects for people to deal with - private final List<HSLFSlideMaster> _masters = new ArrayList<>(); - private final List<HSLFTitleMaster> _titleMasters = new ArrayList<>(); - private final List<HSLFSlide> _slides = new ArrayList<>(); - private final List<HSLFNotes> _notes = new ArrayList<>(); - private FontCollection _fonts; - - - /** - * Constructs a Powerpoint document from the underlying - * HSLFSlideShow object. Finds the model stuff from this - * - * @param hslfSlideShow the HSLFSlideShow to base on - */ - public HSLFSlideShow(HSLFSlideShowImpl hslfSlideShow) { - super(hslfSlideShow.getDirectory()); - - loadSavePhase.set(LoadSavePhase.INIT); - - // Get useful things from our base slideshow - _hslfSlideShow = hslfSlideShow; - - // Handle Parent-aware Records - for (Record record : _hslfSlideShow.getRecords()) { - if(record instanceof RecordContainer){ + private final HSLFSlideShowImpl _hslfSlideShow; + + // 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 Map<Integer,Integer> _sheetIdToCoreRecordsLookup; + + // Records that are interesting + private Document _documentRecord; + + // Friendly objects for people to deal with + private final List<HSLFSlideMaster> _masters = new ArrayList<>(); + private final List<HSLFTitleMaster> _titleMasters = new ArrayList<>(); + private final List<HSLFSlide> _slides = new ArrayList<>(); + private final List<HSLFNotes> _notes = new ArrayList<>(); + private FontCollection _fonts; + + + /** + * Constructs a Powerpoint document from the underlying + * HSLFSlideShow object. Finds the model stuff from this + * + * @param hslfSlideShow the HSLFSlideShow to base on + */ + public HSLFSlideShow(HSLFSlideShowImpl hslfSlideShow) { + super(hslfSlideShow.getDirectory()); + + loadSavePhase.set(LoadSavePhase.INIT); + + // Get useful things from our base slideshow + _hslfSlideShow = hslfSlideShow; + + // Handle Parent-aware Records + for (Record record : _hslfSlideShow.getRecords()) { + if(record instanceof RecordContainer){ RecordContainer.handleParentAwareRecords((RecordContainer)record); } - } + } - // Find the versions of the core records we'll want to use - findMostRecentCoreRecords(); + // Find the versions of the core records we'll want to use + findMostRecentCoreRecords(); - // Build up the model level Slides and Notes - buildSlidesAndNotes(); + // Build up the model level Slides and Notes + buildSlidesAndNotes(); - loadSavePhase.set(LoadSavePhase.LOADED); - } + loadSavePhase.set(LoadSavePhase.LOADED); + } - /** - * Constructs a new, empty, Powerpoint document. - */ - public HSLFSlideShow() { - this(HSLFSlideShowImpl.create()); - } + /** + * Constructs a new, empty, Powerpoint document. + */ + public HSLFSlideShow() { + this(HSLFSlideShowImpl.create()); + } - /** - * Constructs a Powerpoint document from an input stream. - */ - @SuppressWarnings("resource") + /** + * Constructs a Powerpoint document from an input stream. + */ + @SuppressWarnings("resource") public HSLFSlideShow(InputStream inputStream) throws IOException { - this(new HSLFSlideShowImpl(inputStream)); - } + this(new HSLFSlideShowImpl(inputStream)); + } /** * Constructs a Powerpoint document from an POIFSFileSystem. @@ -181,170 +181,170 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh return loadSavePhase.get(); } - /** - * Use the PersistPtrHolder entries to figure out what is the "most recent" - * version of all the core records (Document, Notes, Slide etc), and save a - * record of them. Do this by walking from the oldest PersistPtr to the - * newest, overwriting any references found along the way with newer ones - */ - private void findMostRecentCoreRecords() { - // To start with, find the most recent in the byte offset domain - Map<Integer,Integer> mostRecentByBytes = new HashMap<>(); - 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 id : ids) { - mostRecentByBytes.remove(id); - } - - // Now, update the byte level locations with their latest values - Map<Integer,Integer> thisSetOfLocations = pph.getSlideLocationsLookup(); - for (int id : ids) { - mostRecentByBytes.put(id, thisSetOfLocations.get(id)); - } - } - } - - // We now know how many unique special records we have, so init - // the array - _mostRecentCoreRecords = new Record[mostRecentByBytes.size()]; - - // We'll also want to be able to turn the slide IDs into a position - // in this array - _sheetIdToCoreRecordsLookup = new HashMap<>(); - Integer[] allIDs = mostRecentByBytes.keySet().toArray(new Integer[0]); - Arrays.sort(allIDs); - for (int i = 0; i < allIDs.length; i++) { - _sheetIdToCoreRecordsLookup.put(allIDs[i], i); - } - - Map<Integer,Integer> mostRecentByBytesRev = new HashMap<>(mostRecentByBytes.size()); - for (Map.Entry<Integer,Integer> me : mostRecentByBytes.entrySet()) { - mostRecentByBytesRev.put(me.getValue(), me.getKey()); - } - - // Now convert the byte offsets back into record offsets - for (Record record : _hslfSlideShow.getRecords()) { - if (!(record instanceof PositionDependentRecord)) { + /** + * Use the PersistPtrHolder entries to figure out what is the "most recent" + * version of all the core records (Document, Notes, Slide etc), and save a + * record of them. Do this by walking from the oldest PersistPtr to the + * newest, overwriting any references found along the way with newer ones + */ + private void findMostRecentCoreRecords() { + // To start with, find the most recent in the byte offset domain + Map<Integer,Integer> mostRecentByBytes = new HashMap<>(); + 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 id : ids) { + mostRecentByBytes.remove(id); + } + + // Now, update the byte level locations with their latest values + Map<Integer,Integer> thisSetOfLocations = pph.getSlideLocationsLookup(); + for (int id : ids) { + mostRecentByBytes.put(id, thisSetOfLocations.get(id)); + } + } + } + + // We now know how many unique special records we have, so init + // the array + _mostRecentCoreRecords = new Record[mostRecentByBytes.size()]; + + // We'll also want to be able to turn the slide IDs into a position + // in this array + _sheetIdToCoreRecordsLookup = new HashMap<>(); + Integer[] allIDs = mostRecentByBytes.keySet().toArray(new Integer[0]); + Arrays.sort(allIDs); + for (int i = 0; i < allIDs.length; i++) { + _sheetIdToCoreRecordsLookup.put(allIDs[i], i); + } + + Map<Integer,Integer> mostRecentByBytesRev = new HashMap<>(mostRecentByBytes.size()); + for (Map.Entry<Integer,Integer> me : mostRecentByBytes.entrySet()) { + mostRecentByBytesRev.put(me.getValue(), me.getKey()); + } + + // Now convert the byte offsets back into record offsets + for (Record record : _hslfSlideShow.getRecords()) { + if (!(record instanceof PositionDependentRecord)) { continue; } - PositionDependentRecord pdr = (PositionDependentRecord) record; - int recordAt = pdr.getLastOnDiskOffset(); + PositionDependentRecord pdr = (PositionDependentRecord) record; + int recordAt = pdr.getLastOnDiskOffset(); - Integer thisID = mostRecentByBytesRev.get(recordAt); + Integer thisID = mostRecentByBytesRev.get(recordAt); - if (thisID == null) { + if (thisID == null) { continue; } - // Bingo. Now, where do we store it? - int storeAt = _sheetIdToCoreRecordsLookup.get(thisID); - - // Tell it its Sheet ID, if it cares - if (pdr instanceof PositionDependentRecordContainer) { - PositionDependentRecordContainer pdrc = (PositionDependentRecordContainer) record; - pdrc.setSheetId(thisID); - } - - // Finally, save the record - _mostRecentCoreRecords[storeAt] = record; - } - - // Now look for the interesting records in there - for (Record record : _mostRecentCoreRecords) { - // Check there really is a record at this number - if (record != null) { - // Find the Document, and interesting things in it - if (record.getRecordType() == RecordTypes.Document.typeID) { - _documentRecord = (Document) record; - _fonts = _documentRecord.getEnvironment().getFontCollection(); - } - } /*else { - // No record at this number - // Odd, but not normally a problem - }*/ - } - } - - /** - * For a given SlideAtomsSet, return the core record, based on the refID - * from the SlidePersistAtom - */ - public Record getCoreRecordForSAS(SlideAtomsSet sas) { - SlidePersistAtom spa = sas.getSlidePersistAtom(); - int refID = spa.getRefID(); - return getCoreRecordForRefID(refID); - } - - /** - * For a given refID (the internal, 0 based numbering scheme), return the - * core record - * - * @param refID - * the refID - */ - public Record getCoreRecordForRefID(int refID) { - Integer coreRecordId = _sheetIdToCoreRecordsLookup.get(refID); - if (coreRecordId != null) { - return _mostRecentCoreRecords[coreRecordId]; - } - LOG.atError().log("We tried to look up a reference to a core record, but there was no core ID for reference ID {}", box(refID)); - return null; - } - - /** - * Build up model level Slide and Notes objects, from the underlying - * records. - */ - private void buildSlidesAndNotes() { - // Ensure we really found a Document record earlier - // If we didn't, then the file is probably corrupt - if (_documentRecord == null) { - throw new CorruptPowerPointFileException( - "The PowerPoint file didn't contain a Document Record in its PersistPtr blocks. It is probably corrupt."); - } - - // Fetch the SlideListWithTexts in the most up-to-date Document Record - // - // As far as we understand it: - // * The first SlideListWithText will contain a SlideAtomsSet - // for each of the master slides - // * The second SlideListWithText will contain a SlideAtomsSet - // for each of the slides, in their current order - // These SlideAtomsSets will normally contain text - // * The third SlideListWithText (if present), will contain a - // SlideAtomsSet for each Notes - // These SlideAtomsSets will not normally contain text - // - // Having indentified the masters, slides and notes + their orders, - // we have to go and find their matching records - // We always use the latest versions of these records, and use the - // SlideAtom/NotesAtom to match them with the StyleAtomSet - - findMasterSlides(); - - // Having sorted out the masters, that leaves the notes and slides + // Bingo. Now, where do we store it? + int storeAt = _sheetIdToCoreRecordsLookup.get(thisID); + + // Tell it its Sheet ID, if it cares + if (pdr instanceof PositionDependentRecordContainer) { + PositionDependentRecordContainer pdrc = (PositionDependentRecordContainer) record; + pdrc.setSheetId(thisID); + } + + // Finally, save the record + _mostRecentCoreRecords[storeAt] = record; + } + + // Now look for the interesting records in there + for (Record record : _mostRecentCoreRecords) { + // Check there really is a record at this number + if (record != null) { + // Find the Document, and interesting things in it + if (record.getRecordType() == RecordTypes.Document.typeID) { + _documentRecord = (Document) record; + _fonts = _documentRecord.getEnvironment().getFontCollection(); + } + } /*else { + // No record at this number + // Odd, but not normally a problem + }*/ + } + } + + /** + * For a given SlideAtomsSet, return the core record, based on the refID + * from the SlidePersistAtom + */ + public Record getCoreRecordForSAS(SlideAtomsSet sas) { + SlidePersistAtom spa = sas.getSlidePersistAtom(); + int refID = spa.getRefID(); + return getCoreRecordForRefID(refID); + } + + /** + * For a given refID (the internal, 0 based numbering scheme), return the + * core record + * + * @param refID + * the refID + */ + public Record getCoreRecordForRefID(int refID) { + Integer coreRecordId = _sheetIdToCoreRecordsLookup.get(refID); + if (coreRecordId != null) { + return _mostRecentCoreRecords[coreRecordId]; + } + LOG.atError().log("We tried to look up a reference to a core record, but there was no core ID for reference ID {}", box(refID)); + return null; + } + + /** + * Build up model level Slide and Notes objects, from the underlying + * records. + */ + private void buildSlidesAndNotes() { + // Ensure we really found a Document record earlier + // If we didn't, then the file is probably corrupt + if (_documentRecord == null) { + throw new CorruptPowerPointFileException( + "The PowerPoint file didn't contain a Document Record in its PersistPtr blocks. It is probably corrupt."); + } + + // Fetch the SlideListWithTexts in the most up-to-date Document Record + // + // As far as we understand it: + // * The first SlideListWithText will contain a SlideAtomsSet + // for each of the master slides + // * The second SlideListWithText will contain a SlideAtomsSet + // for each of the slides, in their current order + // These SlideAtomsSets will normally contain text + // * The third SlideListWithText (if present), will contain a + // SlideAtomsSet for each Notes + // These SlideAtomsSets will not normally contain text + // + // Having indentified the masters, slides and notes + their orders, + // we have to go and find their matching records + // We always use the latest versions of these records, and use the + // SlideAtom/NotesAtom to match them with the StyleAtomSet + + findMasterSlides(); + + // Having sorted out the masters, that leaves the notes and slides Map<Integer,Integer> slideIdToNotes = new HashMap<>(); // Start by finding the notes records findNotesSlides(slideIdToNotes); - // Now, do the same thing for our slides - findSlides(slideIdToNotes); - } + // Now, do the same thing for our slides + findSlides(slideIdToNotes); + } - /** + /** * Find master slides * These can be MainMaster records, but oddly they can also be * Slides or Notes, and possibly even other odd stuff.... * About the only thing you can say is that the master details are in the first SLWT. - */ - private void findMasterSlides() { + */ + private void findMasterSlides() { SlideListWithText masterSLWT = _documentRecord.getMasterSlideListWithText(); if (masterSLWT == null) { return; @@ -363,9 +363,9 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh _masters.add(master); } } - } + } - private void findNotesSlides(Map<Integer,Integer> slideIdToNotes) { + private void findNotesSlides(Map<Integer,Integer> slideIdToNotes) { SlideListWithText notesSLWT = _documentRecord.getNotesSlideListWithText(); if (notesSLWT == null) { @@ -384,13 +384,13 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh // we need to add null-records, otherwise the index references to other existing don't work anymore if (r == null) { - LOG.atWarn().log("{}, but that record didn't exist - record ignored.", loggerLoc); + LOG.atWarn().log("{}, but that record didn't exist - record ignored.", loggerLoc); continue; } // Ensure it really is a notes record if (!(r instanceof Notes)) { - LOG.atError().log("{}, but that was actually a {}", loggerLoc, r); + LOG.atError().log("{}, but that was actually a {}", loggerLoc, r); continue; } @@ -404,9 +404,9 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh hn.setSlideShow(this); _notes.add(hn); } - } + } - private void findSlides(Map<Integer,Integer> slideIdToNotes) { + private void findSlides(Map<Integer,Integer> slideIdToNotes) { SlideListWithText slidesSLWT = _documentRecord.getSlideSlideListWithText(); if (slidesSLWT == null) { return; @@ -422,7 +422,7 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh // Ensure it really is a slide record if (!(r instanceof Slide)) { - LOG.atError().log("A Slide SlideAtomSet at {} said its record was at refID {}, but that was actually a {}", box(idx),box(spa.getRefID()),r); + LOG.atError().log("A Slide SlideAtomSet at {} said its record was at refID {}, but that was actually a {}", box(idx),box(spa.getRefID()),r); continue; } @@ -448,36 +448,36 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh hs.setSlideShow(this); _slides.add(hs); } - } - - @Override - public void write(OutputStream out) throws IOException { - // check for text paragraph modifications - for (HSLFSlide sl : getSlides()) { - writeDirtyParagraphs(sl); - } - - for (HSLFSlideMaster sl : getSlideMasters()) { - boolean isDirty = false; - for (List<HSLFTextParagraph> paras : sl.getTextParagraphs()) { - for (HSLFTextParagraph p : paras) { - isDirty |= p.isDirty(); - } - } - if (isDirty) { - for (TxMasterStyleAtom sa : sl.getTxMasterStyleAtoms()) { - if (sa != null) { - // not all master style atoms are set - index 3 is typically null - sa.updateStyles(); - } - } - } - } - - _hslfSlideShow.write(out); - } - - private void writeDirtyParagraphs(HSLFShapeContainer container) { + } + + @Override + public void write(OutputStream out) throws IOException { + // check for text paragraph modifications + for (HSLFSlide sl : getSlides()) { + writeDirtyParagraphs(sl); + } + + for (HSLFSlideMaster sl : getSlideMasters()) { + boolean isDirty = false; + for (List<HSLFTextParagraph> paras : sl.getTextParagraphs()) { + for (HSLFTextParagraph p : paras) { + isDirty |= p.isDirty(); + } + } + if (isDirty) { + for (TxMasterStyleAtom sa : sl.getTxMasterStyleAtoms()) { + if (sa != null) { + // not all master style atoms are set - index 3 is typically null + sa.updateStyles(); + } + } + } + } + + _hslfSlideShow.write(out); + } + + private void writeDirtyParagraphs(HSLFShapeContainer container) { for (HSLFShape sh : container.getShapes()) { if (sh instanceof HSLFShapeContainer) { writeDirtyParagraphs((HSLFShapeContainer)sh); @@ -492,357 +492,357 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh } } } - } - - /** - * Returns an array of the most recent version of all the interesting - * records - */ - public Record[] getMostRecentCoreRecords() { - return _mostRecentCoreRecords; - } - - /** - * Returns an array of all the normal Slides found in the slideshow - */ - @Override - public List<HSLFSlide> getSlides() { - return _slides; - } - - /** - * Returns an array of all the normal Notes found in the slideshow - */ - public List<HSLFNotes> getNotes() { - return _notes; - } - - /** - * Returns an array of all the normal Slide Masters found in the slideshow - */ - @Override - public List<HSLFSlideMaster> getSlideMasters() { - return _masters; - } - - /** - * Returns an array of all the normal Title Masters found in the slideshow - */ - public List<HSLFTitleMaster> getTitleMasters() { - return _titleMasters; - } - - @Override - public List<HSLFPictureData> getPictureData() { - return _hslfSlideShow.getPictureData(); - } - - /** - * Returns the data of all the embedded OLE object in the SlideShow - */ - @SuppressWarnings("WeakerAccess") - public HSLFObjectData[] getEmbeddedObjects() { - return _hslfSlideShow.getEmbeddedObjects(); - } - - /** - * Returns the data of all the embedded sounds in the SlideShow - */ - public HSLFSoundData[] getSoundData() { - return HSLFSoundData.find(_documentRecord); - } - - @Override - public Dimension getPageSize() { - DocumentAtom docatom = _documentRecord.getDocumentAtom(); - int pgx = (int)Units.masterToPoints((int)docatom.getSlideSizeX()); - int pgy = (int)Units.masterToPoints((int)docatom.getSlideSizeY()); - return new Dimension(pgx, pgy); - } - - @Override - public void setPageSize(Dimension pgsize) { - DocumentAtom docatom = _documentRecord.getDocumentAtom(); - docatom.setSlideSizeX(Units.pointsToMaster(pgsize.width)); - docatom.setSlideSizeY(Units.pointsToMaster(pgsize.height)); - } - - /** - * Helper method for usermodel: Get the font collection - */ - FontCollection getFontCollection() { - return _fonts; - } - - /** - * Helper method for usermodel and model: Get the document record - */ - public Document getDocumentRecord() { - return _documentRecord; - } - - /** - * Re-orders a slide, to a new position. - * - * @param oldSlideNumber - * The old slide number (1 based) - * @param newSlideNumber - * The new slide number (1 based) - */ - @SuppressWarnings("WeakerAccess") - public void reorderSlide(int oldSlideNumber, int newSlideNumber) { - // Ensure these numbers are valid - if (oldSlideNumber < 1 || newSlideNumber < 1) { - throw new IllegalArgumentException("Old and new slide numbers must be greater than 0"); - } - if (oldSlideNumber > _slides.size() || newSlideNumber > _slides.size()) { - throw new IllegalArgumentException( - "Old and new slide numbers must not exceed the number of slides (" - + _slides.size() + ")"); - } - - // The order of slides is defined by the order of slide atom sets in the - // SlideListWithText container. - SlideListWithText slwt = _documentRecord.getSlideSlideListWithText(); - if (slwt == null) { - throw new IllegalStateException("Slide record not defined."); - } - SlideAtomsSet[] sas = slwt.getSlideAtomsSets(); - - SlideAtomsSet tmp = sas[oldSlideNumber - 1]; - sas[oldSlideNumber - 1] = sas[newSlideNumber - 1]; - sas[newSlideNumber - 1] = tmp; - - Collections.swap(_slides, oldSlideNumber - 1, newSlideNumber - 1); - _slides.get(newSlideNumber - 1).setSlideNumber(newSlideNumber); - _slides.get(oldSlideNumber - 1).setSlideNumber(oldSlideNumber); - - ArrayList<Record> lst = new ArrayList<>(); - for (SlideAtomsSet s : sas) { - lst.add(s.getSlidePersistAtom()); - lst.addAll(Arrays.asList(s.getSlideRecords())); - } - - Record[] r = lst.toArray(new Record[0]); - slwt.setChildRecord(r); - } - - /** - * Removes the slide at the given index (0-based). - * <p> - * Shifts any subsequent slides to the left (subtracts one from their slide - * numbers). - * </p> - * - * @param index - * the index of the slide to remove (0-based) - * @return the slide that was removed from the slide show. - */ - @SuppressWarnings("WeakerAccess") - public HSLFSlide removeSlide(int index) { - int lastSlideIdx = _slides.size() - 1; - if (index < 0 || index > lastSlideIdx) { - throw new IllegalArgumentException("Slide index (" + index + ") is out of range (0.." - + lastSlideIdx + ")"); - } - - SlideListWithText slwt = _documentRecord.getSlideSlideListWithText(); - if (slwt == null) { - throw new IllegalStateException("Slide record not defined."); - } - SlideAtomsSet[] sas = slwt.getSlideAtomsSets(); - - List<Record> records = new ArrayList<>(); - List<SlideAtomsSet> sa = new ArrayList<>(Arrays.asList(sas)); - - HSLFSlide removedSlide = _slides.remove(index); - _notes.remove(removedSlide.getNotes()); - sa.remove(index); - - int i=0; - for (HSLFSlide s : _slides) { + } + + /** + * Returns an array of the most recent version of all the interesting + * records + */ + public Record[] getMostRecentCoreRecords() { + return _mostRecentCoreRecords; + } + + /** + * Returns an array of all the normal Slides found in the slideshow + */ + @Override + public List<HSLFSlide> getSlides() { + return _slides; + } + + /** + * Returns an array of all the normal Notes found in the slideshow + */ + public List<HSLFNotes> getNotes() { + return _notes; + } + + /** + * Returns an array of all the normal Slide Masters found in the slideshow + */ + @Override + public List<HSLFSlideMaster> getSlideMasters() { + return _masters; + } + + /** + * Returns an array of all the normal Title Masters found in the slideshow + */ + public List<HSLFTitleMaster> getTitleMasters() { + return _titleMasters; + } + + @Override + public List<HSLFPictureData> getPictureData() { + return _hslfSlideShow.getPictureData(); + } + + /** + * Returns the data of all the embedded OLE object in the SlideShow + */ + @SuppressWarnings("WeakerAccess") + public HSLFObjectData[] getEmbeddedObjects() { + return _hslfSlideShow.getEmbeddedObjects(); + } + + /** + * Returns the data of all the embedded sounds in the SlideShow + */ + public HSLFSoundData[] getSoundData() { + return HSLFSoundData.find(_documentRecord); + } + + @Override + public Dimension getPageSize() { + DocumentAtom docatom = _documentRecord.getDocumentAtom(); + int pgx = (int)Units.masterToPoints((int)docatom.getSlideSizeX()); + int pgy = (int)Units.masterToPoints((int)docatom.getSlideSizeY()); + return new Dimension(pgx, pgy); + } + + @Override + public void setPageSize(Dimension pgsize) { + DocumentAtom docatom = _documentRecord.getDocumentAtom(); + docatom.setSlideSizeX(Units.pointsToMaster(pgsize.width)); + docatom.setSlideSizeY(Units.pointsToMaster(pgsize.height)); + } + + /** + * Helper method for usermodel: Get the font collection + */ + FontCollection getFontCollection() { + return _fonts; + } + + /** + * Helper method for usermodel and model: Get the document record + */ + public Document getDocumentRecord() { + return _documentRecord; + } + + /** + * Re-orders a slide, to a new position. + * + * @param oldSlideNumber + * The old slide number (1 based) + * @param newSlideNumber + * The new slide number (1 based) + */ + @SuppressWarnings("WeakerAccess") + public void reorderSlide(int oldSlideNumber, int newSlideNumber) { + // Ensure these numbers are valid + if (oldSlideNumber < 1 || newSlideNumber < 1) { + throw new IllegalArgumentException("Old and new slide numbers must be greater than 0"); + } + if (oldSlideNumber > _slides.size() || newSlideNumber > _slides.size()) { + throw new IllegalArgumentException( + "Old and new slide numbers must not exceed the number of slides (" + + _slides.size() + ")"); + } + + // The order of slides is defined by the order of slide atom sets in the + // SlideListWithText container. + SlideListWithText slwt = _documentRecord.getSlideSlideListWithText(); + if (slwt == null) { + throw new IllegalStateException("Slide record not defined."); + } + SlideAtomsSet[] sas = slwt.getSlideAtomsSets(); + + SlideAtomsSet tmp = sas[oldSlideNumber - 1]; + sas[oldSlideNumber - 1] = sas[newSlideNumber - 1]; + sas[newSlideNumber - 1] = tmp; + + Collections.swap(_slides, oldSlideNumber - 1, newSlideNumber - 1); + _slides.get(newSlideNumber - 1).setSlideNumber(newSlideNumber); + _slides.get(oldSlideNumber - 1).setSlideNumber(oldSlideNumber); + + ArrayList<Record> lst = new ArrayList<>(); + for (SlideAtomsSet s : sas) { + lst.add(s.getSlidePersistAtom()); + lst.addAll(Arrays.asList(s.getSlideRecords())); + } + + Record[] r = lst.toArray(new Record[0]); + slwt.setChildRecord(r); + } + + /** + * Removes the slide at the given index (0-based). + * <p> + * Shifts any subsequent slides to the left (subtracts one from their slide + * numbers). + * </p> + * + * @param index + * the index of the slide to remove (0-based) + * @return the slide that was removed from the slide show. + */ + @SuppressWarnings("WeakerAccess") + public HSLFSlide removeSlide(int index) { + int lastSlideIdx = _slides.size() - 1; + if (index < 0 || index > lastSlideIdx) { + throw new IllegalArgumentException("Slide index (" + index + ") is out of range (0.." + + lastSlideIdx + ")"); + } + + SlideListWithText slwt = _documentRecord.getSlideSlideListWithText(); + if (slwt == null) { + throw new IllegalStateException("Slide record not defined."); + } + SlideAtomsSet[] sas = slwt.getSlideAtomsSets(); + + List<Record> records = new ArrayList<>(); + List<SlideAtomsSet> sa = new ArrayList<>(Arrays.asList(sas)); + + HSLFSlide removedSlide = _slides.remove(index); + _notes.remove(removedSlide.getNotes()); + sa.remove(index); + + int i=0; + for (HSLFSlide s : _slides) { s.setSlideNumber(i++); } - for (SlideAtomsSet s : sa) { + for (SlideAtomsSet s : sa) { records.add(s.getSlidePersistAtom()); records.addAll(Arrays.asList(s.getSlideRecords())); - } - if (sa.isEmpty()) { - _documentRecord.removeSlideListWithText(slwt); - } else { - slwt.setSlideAtomsSets(sa.toArray(new SlideAtomsSet[0])); - slwt.setChildRecord(records.toArray(new Record[0])); - } + } + if (sa.isEmpty()) { + _documentRecord.removeSlideListWithText(slwt); + } else { + slwt.setSlideAtomsSets(sa.toArray(new SlideAtomsSet[0])); + slwt.setChildRecord(records.toArray(new Record[0])); + } - // if the removed slide had notes - remove references to them too + // if the removed slide had notes - remove references to them too int notesId = removedSlide.getSlideRecord().getSlideAtom().getNotesID(); - if (notesId != 0) { - SlideListWithText nslwt = _documentRecord.getNotesSlideListWithText(); - records = new ArrayList<>(); - ArrayList<SlideAtomsSet> na = new ArrayList<>(); - if (nslwt != null) { - for (SlideAtomsSet ns : nslwt.getSlideAtomsSets()) { - if (ns.getSlidePersistAtom().getSlideIdentifier() == notesId) { - continue; - } - na.add(ns); - records.add(ns.getSlidePersistAtom()); - if (ns.getSlideRecords() != null) { - records.addAll(Arrays.asList(ns.getSlideRecords())); - } - } - - if (!na.isEmpty()) { - nslwt.setSlideAtomsSets(na.toArray(new SlideAtomsSet[0])); - nslwt.setChildRecord(records.toArray(new Record[0])); - } - } - if (na.isEmpty()) { - _documentRecord.removeSlideListWithText(nslwt); - } - } - - return removedSlide; - } - - /** - * Create a blank {@code Slide}. - * - * @return the created {@code Slide} - */ - @Override - public HSLFSlide createSlide() { - // We need to add the records to the SLWT that deals - // with Slides. - // Add it, if it doesn't exist - SlideListWithText slist = _documentRecord.getSlideSlideListWithText(); - if (slist == null) { - // Need to add a new one - slist = new SlideListWithText(); - slist.setInstance(SlideListWithText.SLIDES); - _documentRecord.addSlideListWithText(slist); - } - - // Grab the SlidePersistAtom with the highest Slide Number. - // (Will stay as null if no SlidePersistAtom exists yet in - // the slide, or only master slide's ones do) - SlidePersistAtom prev = null; - for (SlideAtomsSet sas : slist.getSlideAtomsSets()) { - SlidePersistAtom spa = sas.getSlidePersistAtom(); - if (spa.getSlideIdentifier() >= 0) { - // Must be for a real slide - if (prev == null) { - prev = spa; - } - if (prev.getSlideIdentifier() < spa.getSlideIdentifier()) { - prev = spa; - } - } - } - - // Set up a new SlidePersistAtom for this slide - SlidePersistAtom sp = new SlidePersistAtom(); - - // First slideId is always 256 - sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1)); - - // Add this new SlidePersistAtom to the SlideListWithText - slist.addSlidePersistAtom(sp); - - // Create a new Slide - HSLFSlide slide = new HSLFSlide(sp.getSlideIdentifier(), sp.getRefID(), _slides.size() + 1); - slide.setSlideShow(this); - slide.onCreate(); - - // Add in to the list of Slides - _slides.add(slide); - LOG.atInfo().log("Added slide {} with ref {} and identifier {}", box(_slides.size()),box(sp.getRefID()),box(sp.getSlideIdentifier())); - - // Add the core records for this new Slide to the record tree - Slide slideRecord = slide.getSlideRecord(); - int psrId = addPersistentObject(slideRecord); - sp.setRefID(psrId); - slideRecord.setSheetId(psrId); - - slide.setMasterSheet(_masters.get(0)); - // All done and added - return slide; - } - - @Override - public HSLFPictureData addPicture(byte[] data, PictureType format) throws IOException { - if (format == null || format.nativeId == -1) { - throw new IllegalArgumentException("Unsupported picture format: " + format); - } - - HSLFPictureData pd = findPictureData(data); - if (pd != null) { - // identical picture was already added to the SlideShow - return pd; - } - - EscherContainerRecord bstore; - - EscherContainerRecord dggContainer = _documentRecord.getPPDrawingGroup().getDggContainer(); - bstore = HSLFShape.getEscherChild(dggContainer, - EscherContainerRecord.BSTORE_CONTAINER); - if (bstore == null) { - bstore = new EscherContainerRecord(); - bstore.setRecordId(EscherContainerRecord.BSTORE_CONTAINER); - - dggContainer.addChildBefore(bstore, EscherOptRecord.RECORD_ID); - } - - EscherBSERecord bse = addNewEscherBseRecord(bstore, format, data, 0); - HSLFPictureData pict = HSLFPictureData.createFromImageData(format, bstore, bse, data); - - int offset = _hslfSlideShow.addPicture(pict); - bse.setOffset(offset); - - return pict; - } - - /** - * Adds a picture to the presentation. - * - * @param is The stream to read the image from - * @param format The format of the picture. - * - * @return the picture data. - * @since 3.15 beta 2 - */ - @Override - public HSLFPictureData addPicture(InputStream is, PictureType format) throws IOException { - if (format == null || format.nativeId == -1) { // fail early - throw new IllegalArgumentException("Unsupported picture format: " + format); - } - return addPicture(IOUtils.toByteArray(is), format); - } - - /** - * Adds a picture to the presentation. - * - * @param pict - * the file containing the image to add - * @param format - * The format of the picture. - * - * @return the picture data. - * @since 3.15 beta 2 - */ - @Override - public HSLFPictureData addPicture(File pict, PictureType format) throws IOException { - if (format == null || format.nativeId == -1) { // fail early - throw new IllegalArgumentException("Unsupported picture format: " + format); - } - byte[] data = IOUtils.safelyAllocate(pict.length(), MAX_RECORD_LENGTH); - try (FileInputStream is = new FileInputStream(pict)) { - IOUtils.readFully(is, data); - } - return addPicture(data, format); - } + if (notesId != 0) { + SlideListWithText nslwt = _documentRecord.getNotesSlideListWithText(); + records = new ArrayList<>(); + ArrayList<SlideAtomsSet> na = new ArrayList<>(); + if (nslwt != null) { + for (SlideAtomsSet ns : nslwt.getSlideAtomsSets()) { + if (ns.getSlidePersistAtom().getSlideIdentifier() == notesId) { + continue; + } + na.add(ns); + records.add(ns.getSlidePersistAtom()); + if (ns.getSlideRecords() != null) { + records.addAll(Arrays.asList(ns.getSlideRecords())); + } + } + + if (!na.isEmpty()) { + nslwt.setSlideAtomsSets(na.toArray(new SlideAtomsSet[0])); + nslwt.setChildRecord(records.toArray(new Record[0])); + } + } + if (na.isEmpty()) { + _documentRecord.removeSlideListWithText(nslwt); + } + } + + return removedSlide; + } + + /** + * Create a blank {@code Slide}. + * + * @return the created {@code Slide} + */ + @Override + public HSLFSlide createSlide() { + // We need to add the records to the SLWT that deals + // with Slides. + // Add it, if it doesn't exist + SlideListWithText slist = _documentRecord.getSlideSlideListWithText(); + if (slist == null) { + // Need to add a new one + slist = new SlideListWithText(); + slist.setInstance(SlideListWithText.SLIDES); + _documentRecord.addSlideListWithText(slist); + } + + // Grab the SlidePersistAtom with the highest Slide Number. + // (Will stay as null if no SlidePersistAtom exists yet in + // the slide, or only master slide's ones do) + SlidePersistAtom prev = null; + for (SlideAtomsSet sas : slist.getSlideAtomsSets()) { + SlidePersistAtom spa = sas.getSlidePersistAtom(); + if (spa.getSlideIdentifier() >= 0) { + // Must be for a real slide + if (prev == null) { + prev = spa; + } + if (prev.getSlideIdentifier() < spa.getSlideIdentifier()) { + prev = spa; + } + } + } + + // Set up a new SlidePersistAtom for this slide + SlidePersistAtom sp = new SlidePersistAtom(); + + // First slideId is always 256 + sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1)); + + // Add this new SlidePersistAtom to the SlideListWithText + slist.addSlidePersistAtom(sp); + + // Create a new Slide + HSLFSlide slide = new HSLFSlide(sp.getSlideIdentifier(), sp.getRefID(), _slides.size() + 1); + slide.setSlideShow(this); + slide.onCreate(); + + // Add in to the list of Slides + _slides.add(slide); + LOG.atInfo().log("Added slide {} with ref {} and identifier {}", box(_slides.size()),box(sp.getRefID()),box(sp.getSlideIdentifier())); + + // Add the core records for this new Slide to the record tree + Slide slideRecord = slide.getSlideRecord(); + int psrId = addPersistentObject(slideRecord); + sp.setRefID(psrId); + slideRecord.setSheetId(psrId); + + slide.setMasterSheet(_masters.get(0)); + // All done and added + return slide; + } + + @Override + public HSLFPictureData addPicture(byte[] data, PictureType format) throws IOException { + if (format == null || format.nativeId == -1) { + throw new IllegalArgumentException("Unsupported picture format: " + format); + } + + HSLFPictureData pd = findPictureData(data); + if (pd != null) { + // identical picture was already added to the SlideShow + return pd; + } + + EscherContainerRecord bstore; + + EscherContainerRecord dggContainer = _documentRecord.getPPDrawingGroup().getDggContainer(); + bstore = HSLFShape.getEscherChild(dggContainer, + EscherContainerRecord.BSTORE_CONTAINER); + if (bstore == null) { + bstore = new EscherContainerRecord(); + bstore.setRecordId(EscherContainerRecord.BSTORE_CONTAINER); + + dggContainer.addChildBefore(bstore, EscherOptRecord.RECORD_ID); + } + + EscherBSERecord bse = addNewEscherBseRecord(bstore, format, data, 0); + HSLFPictureData pict = HSLFPictureData.createFromImageData(format, bstore, bse, data); + + int offset = _hslfSlideShow.addPicture(pict); + bse.setOffset(offset); + + return pict; + } + + /** + * Adds a picture to the presentation. + * + * @param is The stream to read the image from + * @param format The format of the picture. + * + * @return the picture data. + * @since 3.15 beta 2 + */ + @Override + public HSLFPictureData addPicture(InputStream is, PictureType format) throws IOException { + if (format == null || format.nativeId == -1) { // fail early + throw new IllegalArgumentException("Unsupported picture format: " + format); + } + return addPicture(IOUtils.toByteArray(is), format); + } + + /** + * Adds a picture to the presentation. + * + * @param pict + * the file containing the image to add + * @param format + * The format of the picture. + * + * @return the picture data. + * @since 3.15 beta 2 + */ + @Override + public HSLFPictureData addPicture(File pict, PictureType format) throws IOException { + if (format == null || format.nativeId == -1) { // fail early + throw new IllegalArgumentException("Unsupported picture format: " + format); + } + byte[] data = IOUtils.safelyAllocate(pict.length(), MAX_RECORD_LENGTH); + try (FileInputStream is = new FileInputStream(pict)) { + IOUtils.readFully(is, data); + } + return addPicture(data, format); + } /** * check if a picture with this picture data already exists in this presentation @@ -863,164 +863,164 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh return null; } - /** - * Add a font in this presentation - * - * @param fontInfo the font to add - * @return the registered HSLFFontInfo - the font info object is unique based on the typeface - */ - public HSLFFontInfo addFont(FontInfo fontInfo) { - return getDocumentRecord().getEnvironment().getFontCollection().addFont(fontInfo); - } - - /** - * Add a font in this presentation and also embed its font data - * - * @param fontData the EOT font data as stream - * - * @return the registered HSLFFontInfo - the font info object is unique based on the typeface - * - * @since POI 4.1.0 - */ - @Override - public HSLFFontInfo addFont(InputStream fontData) throws IOException { - Document doc = getDocumentRecord(); - doc.getDocumentAtom().setSaveWithFonts(true); - return doc.getEnvironment().getFontCollection().addFont(fontData); - } - - /** - * Get a font by index - * - * @param idx - * 0-based index of the font - * @return of an instance of {@code PPFont} or {@code null} if not - * found - */ - public HSLFFontInfo getFont(int idx) { - return getDocumentRecord().getEnvironment().getFontCollection().getFontInfo(idx); - } - - /** - * get the number of fonts in the presentation - * - * @return number of fonts - */ - public int getNumberOfFonts() { - return getDocumentRecord().getEnvironment().getFontCollection().getNumberOfFonts(); - } - - @Override - public List<HSLFFontInfo> getFonts() { - return getDocumentRecord().getEnvironment().getFontCollection().getFonts(); - } - - /** - * Return Header / Footer settings for slides - * - * @return Header / Footer settings for slides - */ - public HeadersFooters getSlideHeadersFooters() { - return new HeadersFooters(this, HeadersFootersContainer.SlideHeadersFootersContainer); - } - - /** - * Return Header / Footer settings for notes - * - * @return Header / Footer settings for notes - */ - public HeadersFooters getNotesHeadersFooters() { - if (_notes.isEmpty()) { - return new HeadersFooters(this, HeadersFootersContainer.NotesHeadersFootersContainer); - } else { - return new HeadersFooters(_notes.get(0), HeadersFootersContainer.NotesHeadersFootersContainer); - } - } - - /** - * Add a movie in this presentation - * - * @param path - * the path or url to the movie - * @return 0-based index of the movie - */ - public int addMovie(String path, int type) { - ExMCIMovie mci; - switch (type) { - case MovieShape.MOVIE_MPEG: - mci = new ExMCIMovie(); - break; - case MovieShape.MOVIE_AVI: - mci = new ExAviMovie(); - break; - default: - throw new IllegalArgumentException("Unsupported Movie: " + type); - } - - ExVideoContainer exVideo = mci.getExVideo(); - exVideo.getExMediaAtom().setMask(0xE80000); - exVideo.getPathAtom().setText(path); - - int objectId = addToObjListAtom(mci); - exVideo.getExMediaAtom().setObjectId(objectId); - - return objectId; - } - - /** - * Add a control in this presentation - * - * @param name - * name of the control, e.g. "Shockwave Flash Object" - * @param progId - * OLE Programmatic Identifier, e.g. - * "ShockwaveFlash.ShockwaveFlash.9" - * @return 0-based index of the control - */ - @SuppressWarnings("unused") - public int addControl(String name, String progId) { - ExControl ctrl = new ExControl(); - ctrl.setProgId(progId); - ctrl.setMenuName(name); - ctrl.setClipboardName(name); - - ExOleObjAtom oleObj = ctrl.getExOleObjAtom(); - oleObj.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); - oleObj.setType(ExOleObjAtom.TYPE_CONTROL); - oleObj.setSubType(ExOleObjAtom.SUBTYPE_DEFAULT); - - int objectId = addToObjListAtom(ctrl); - oleObj.setObjID(objectId); - return objectId; - } - - /** - * Add a embedded object to this presentation - * - * @return 0-based index of the embedded object - */ - public int addEmbed(POIFSFileSystem poiData) { + /** + * Add a font in this presentation + * + * @param fontInfo the font to add + * @return the registered HSLFFontInfo - the font info object is unique based on the typeface + */ + public HSLFFontInfo addFont(FontInfo fontInfo) { + return getDocumentRecord().getEnvironment().getFontCollection().addFont(fontInfo); + } + + /** + * Add a font in this presentation and also embed its font data + * + * @param fontData the EOT font data as stream + * + * @return the registered HSLFFontInfo - the font info object is unique based on the typeface + * + * @since POI 4.1.0 + */ + @Override + public HSLFFontInfo addFont(InputStream fontData) throws IOException { + Document doc = getDocumentRecord(); + doc.getDocumentAtom().setSaveWithFonts(true); + return doc.getEnvironment().getFontCollection().addFont(fontData); + } + + /** + * Get a font by index + * + * @param idx + * 0-based index of the font + * @return of an instance of {@code PPFont} or {@code null} if not + * found + */ + public HSLFFontInfo getFont(int idx) { + return getDocumentRecord().getEnvironment().getFontCollection().getFontInfo(idx); + } + + /** + * get the number of fonts in the presentation + * + * @return number of fonts + */ + public int getNumberOfFonts() { + return getDocumentRecord().getEnvironment().getFontCollection().getNumberOfFonts(); + } + + @Override + public List<HSLFFontInfo> getFonts() { + return getDocumentRecord().getEnvironment().getFontCollection().getFonts(); + } + + /** + * Return Header / Footer settings for slides + * + * @return Header / Footer settings for slides + */ + public HeadersFooters getSlideHeadersFooters() { + return new HeadersFooters(this, HeadersFootersContainer.SlideHeadersFootersContainer); + } + + /** + * Return Header / Footer settings for notes + * + * @return Header / Footer settings for notes + */ + public HeadersFooters getNotesHeadersFooters() { + if (_notes.isEmpty()) { + return new HeadersFooters(this, HeadersFootersContainer.NotesHeadersFootersContainer); + } else { + return new HeadersFooters(_notes.get(0), HeadersFootersContainer.NotesHeadersFootersContainer); + } + } + + /** + * Add a movie in this presentation + * + * @param path + * the path or url to the movie + * @return 0-based index of the movie + */ + public int addMovie(String path, int type) { + ExMCIMovie mci; + switch (type) { + case MovieShape.MOVIE_MPEG: + mci = new ExMCIMovie(); + break; + case MovieShape.MOVIE_AVI: + mci = new ExAviMovie(); + break; + default: + throw new IllegalArgumentException("Unsupported Movie: " + type); + } + + ExVideoContainer exVideo = mci.getExVideo(); + exVideo.getExMediaAtom().setMask(0xE80000); + exVideo.getPathAtom().setText(path); + + int objectId = addToObjListAtom(mci); + exVideo.getExMediaAtom().setObjectId(objectId); + + return objectId; + } + + /** + * Add a control in this presentation + * + * @param name + * name of the control, e.g. "Shockwave Flash Object" + * @param progId + * OLE Programmatic Identifier, e.g. + * "ShockwaveFlash.ShockwaveFlash.9" + * @return 0-based index of the control + */ + @SuppressWarnings("unused") + public int addControl(String name, String progId) { + ExControl ctrl = new ExControl(); + ctrl.setProgId(progId); + ctrl.setMenuName(name); + ctrl.setClipboardName(name); + + ExOleObjAtom oleObj = ctrl.getExOleObjAtom(); + oleObj.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); + oleObj.setType(ExOleObjAtom.TYPE_CONTROL); + oleObj.setSubType(ExOleObjAtom.SUBTYPE_DEFAULT); + + int objectId = addToObjListAtom(ctrl); + oleObj.setObjID(objectId); + return objectId; + } + + /** + * Add a embedded object to this presentation + * + * @return 0-based index of the embedded object + */ + public int addEmbed(POIFSFileSystem poiData) { DirectoryNode root = poiData.getRoot(); // prepare embedded data if (new ClassID().equals(root.getStorageClsid())) { - // need to set class id - Map<String,ClassID> olemap = getOleMap(); - ClassID classID = null; - for (Map.Entry<String,ClassID> entry : olemap.entrySet()) { - if (root.hasEntry(entry.getKey())) { - classID = entry.getValue(); - break; - } - } - if (classID == null) { - throw new IllegalArgumentException("Unsupported embedded document"); - } - - root.setStorageClsid(classID); + // need to set class id + Map<String,ClassID> olemap = getOleMap(); + ClassID classID = null; + for (Map.Entry<String,ClassID> entry : olemap.entrySet()) { + if (root.hasEntry(entry.getKey())) { + classID = entry.getValue(); + break; + } + } + if (classID == null) { + throw new IllegalArgumentException("Unsupported embedded document"); + } + + root.setStorageClsid(classID); } - ExEmbed exEmbed = new ExEmbed(); + ExEmbed exEmbed = new ExEmbed(); // remove unneccessary infos, so we don't need to specify the type // of the ole object multiple times Record[] children = exEmbed.getChildRecords(); @@ -1041,92 +1041,92 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh ExOleObjStg exOleObjStg = new ExOleObjStg(); try { Ole10Native.createOleMarkerEntry(poiData); - UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream(); - poiData.writeFilesystem(bos); - exOleObjStg.setData(bos.toByteArray()); + UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream(); + poiData.writeFilesystem(bos); + exOleObjStg.setData(bos.toByteArray()); } catch (IOException e) { - throw new HSLFException(e); + throw new HSLFException(e); } int psrId = addPersistentObject(exOleObjStg); exOleObjStg.setPersistId(psrId); eeAtom.setObjStgDataRef(psrId); - int objectId = addToObjListAtom(exEmbed); - eeAtom.setObjID(objectId); - return objectId; - } + int objectId = addToObjListAtom(exEmbed); + eeAtom.setObjID(objectId); + return objectId; + } - @Override + @Override public HPSFPropertiesExtractor getMetadataTextExtractor() { return new HPSFPropertiesExtractor(getSlideShowImpl()); } - int addToObjListAtom(RecordContainer exObj) { - ExObjList lst = getDocumentRecord().getExObjList(true); - ExObjListAtom objAtom = lst.getExObjListAtom(); - // increment the object ID seed - int objectId = (int) objAtom.getObjectIDSeed() + 1; - objAtom.setObjectIDSeed(objectId); + int addToObjListAtom(RecordContainer exObj) { + ExObjList lst = getDocumentRecord().getExObjList(true); + ExObjListAtom objAtom = lst.getExObjListAtom(); + // increment the object ID seed + int objectId = (int) objAtom.getObjectIDSeed() + 1; + objAtom.setObjectIDSeed(objectId); - lst.addChildAfter(exObj, objAtom); + lst.addChildAfter(exObj, objAtom); - return objectId; - } + return objectId; + } private static Map<String,ClassID> getOleMap() { - Map<String,ClassID> olemap = new HashMap<>(); - olemap.put(POWERPOINT_DOCUMENT, ClassIDPredefined.POWERPOINT_V8.getClassID()); - // as per BIFF8 spec - olemap.put("Workbook", ClassIDPredefined.EXCEL_V8.getClassID()); - // Typically from third party programs - olemap.put("WORKBOOK", ClassIDPredefined.EXCEL_V8.getClassID()); - // Typically odd Crystal Reports exports - olemap.put("BOOK", ClassIDPredefined.EXCEL_V8.getClassID()); - // ... to be continued - return olemap; + Map<String,ClassID> olemap = new HashMap<>(); + olemap.put(POWERPOINT_DOCUMENT, ClassIDPredefined.POWERPOINT_V8.getClassID()); + // as per BIFF8 spec + olemap.put("Workbook", ClassIDPredefined.EXCEL_V8.getClassID()); + // Typically from third party programs + olemap.put("WORKBOOK", ClassIDPredefined.EXCEL_V8.getClassID()); + // Typically odd Crystal Reports exports + olemap.put("BOOK", ClassIDPredefined.EXCEL_V8.getClassID()); + // ... to be continued + return olemap; } private int addPersistentObject(PositionDependentRecord slideRecord) { - slideRecord.setLastOnDiskOffset(HSLFSlideShowImpl.UNSET_OFFSET); - _hslfSlideShow.appendRootLevelRecord((Record)slideRecord); + slideRecord.setLastOnDiskOffset(HSLFSlideShowImpl.UNSET_OFFSET); + _hslfSlideShow.appendRootLevelRecord((Record)slideRecord); // 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,PositionDependentRecord> interestingRecords = + Map<RecordTypes,PositionDependentRecord> interestingRecords = new HashMap<>(); - try { + 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); + 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; + // persist ID is UserEditAtom.maxPersistWritten + 1 + int psrId = usr.getMaxPersistWritten() + 1; - // Last view is now of the slide - usr.setLastViewType((short) UserEditAtom.LAST_VIEW_SLIDE_VIEW); - // increment the number of persistent objects - usr.setMaxPersistWritten(psrId); + // Last view is now of the slide + usr.setLastViewType((short) UserEditAtom.LAST_VIEW_SLIDE_VIEW); + // increment the number of persistent objects + usr.setMaxPersistWritten(psrId); - // 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); - LOG.atInfo().log("New slide/object ended up at {}", box(slideOffset)); + // 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); + LOG.atInfo().log("New slide/object ended up at {}", box(slideOffset)); - return psrId; + return psrId; } @Override public MasterSheet<HSLFShape,HSLFTextParagraph> createMasterSheet() { - // TODO implement or throw exception if not supported + // TODO implement or throw exception if not supported return null; } @@ -1143,138 +1143,138 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh _hslfSlideShow.close(); } - @Override - public Object getPersistDocument() { - return getSlideShowImpl(); - } - - @Override - public Map<String, Supplier<?>> getGenericProperties() { - return GenericRecordUtil.getGenericProperties( - "pictures", this::getPictureData, - "embeddedObjects", this::getEmbeddedObjects - ); - } - - @Override - public List<? extends GenericRecord> getGenericChildren() { - return Arrays.asList(_hslfSlideShow.getRecords()); - } - - @Override - public void write() throws IOException { - getSlideShowImpl().write(); - } - - @Override - public void write(File newFile) throws IOException { - getSlideShowImpl().write(newFile); - } - - @Override - public DocumentSummaryInformation getDocumentSummaryInformation() { - return getSlideShowImpl().getDocumentSummaryInformation(); - } - - @Override - public SummaryInformation getSummaryInformation() { - return getSlideShowImpl().getSummaryInformation(); - } - - @Override - public void createInformationProperties() { - getSlideShowImpl().createInformationProperties(); - } - - @Override - public void readProperties() { - getSlideShowImpl().readProperties(); - } - - @Override - protected PropertySet getPropertySet(String setName) throws IOException { - return getSlideShowImpl().getPropertySetImpl(setName); - } - - @Override - protected PropertySet getPropertySet(String setName, EncryptionInfo encryptionInfo) throws IOException { - return getSlideShowImpl().getPropertySetImpl(setName, encryptionInfo); - } - - @Override - protected void writeProperties() throws IOException { - getSlideShowImpl().writePropertiesImpl(); - } - - @Override - public void writeProperties(POIFSFileSystem outFS) throws IOException { - getSlideShowImpl().writeProperties(outFS); - } - - @Override - protected void writeProperties(POIFSFileSystem outFS, List<String> writtenEntries) throws IOException { - getSlideShowImpl().writePropertiesImpl(outFS, writtenEntries); - } - - @Override - protected void validateInPlaceWritePossible() throws IllegalStateException { - getSlideShowImpl().validateInPlaceWritePossibleImpl(); - } - - @Override - public DirectoryNode getDirectory() { - return getSlideShowImpl().getDirectory(); - } - - @Override - protected void clearDirectory() { - getSlideShowImpl().clearDirectoryImpl(); - } - - @Override - protected boolean initDirectory() { - return getSlideShowImpl().initDirectoryImpl(); - } - - @Override - protected void replaceDirectory(DirectoryNode newDirectory) throws IOException { - getSlideShowImpl().replaceDirectoryImpl(newDirectory); - } - - @Override - protected String getEncryptedPropertyStreamName() { - return getSlideShowImpl().getEncryptedPropertyStreamName(); - } - - @Override - public EncryptionInfo getEncryptionInfo() { - return getSlideShowImpl().getEncryptionInfo(); - } - - static EscherBSERecord addNewEscherBseRecord(EscherContainerRecord blipStore, PictureType type, byte[] imageData, int offset) { - EscherBSERecord record = new EscherBSERecord(); - record.setRecordId(EscherBSERecord.RECORD_ID); - record.setOptions((short) (0x0002 | (type.nativeId << 4))); - record.setSize(imageData.length + HSLFPictureData.PREAMBLE_SIZE); - record.setUid(Arrays.copyOf(imageData, HSLFPictureData.CHECKSUM_SIZE)); - - record.setBlipTypeMacOS((byte) type.nativeId); - record.setBlipTypeWin32((byte) type.nativeId); - - if (type == PictureType.EMF) { - record.setBlipTypeMacOS((byte) PictureType.PICT.nativeId); - } else if (type == PictureType.WMF) { - record.setBlipTypeMacOS((byte) PictureType.PICT.nativeId); - } else if (type == PictureType.PICT) { - record.setBlipTypeWin32((byte) PictureType.WMF.nativeId); - } - - record.setOffset(offset); - - blipStore.addChildRecord(record); - int count = blipStore.getChildCount(); - blipStore.setOptions((short) ((count << 4) | 0xF)); - - return record; - } + @Override + public Object getPersistDocument() { + return getSlideShowImpl(); + } + + @Override + public Map<String, Supplier<?>> getGenericProperties() { + return GenericRecordUtil.getGenericProperties( + "pictures", this::getPictureData, + "embeddedObjects", this::getEmbeddedObjects + ); + } + + @Override + public List<? extends GenericRecord> getGenericChildren() { + return Arrays.asList(_hslfSlideShow.getRecords()); + } + + @Override + public void write() throws IOException { + getSlideShowImpl().write(); + } + + @Override + public void write(File newFile) throws IOException { + getSlideShowImpl().write(newFile); + } + + @Override + public DocumentSummaryInformation getDocumentSummaryInformation() { + return getSlideShowImpl().getDocumentSummaryInformation(); + } + + @Override + public SummaryInformation getSummaryInformation() { + return getSlideShowImpl().getSummaryInformation(); + } + + @Override + public void createInformationProperties() { + getSlideShowImpl().createInformationProperties(); + } + + @Override + public void readProperties() { + getSlideShowImpl().readProperties(); + } + + @Override + protected PropertySet getPropertySet(String setName) throws IOException { + return getSlideShowImpl().getPropertySetImpl(setName); + } + + @Override + protected PropertySet getPropertySet(String setName, EncryptionInfo encryptionInfo) throws IOException { + return getSlideShowImpl().getPropertySetImpl(setName, encryptionInfo); + } + + @Override + protected void writeProperties() throws IOException { + getSlideShowImpl().writePropertiesImpl(); + } + + @Override + public void writeProperties(POIFSFileSystem outFS) throws IOException { + getSlideShowImpl().writeProperties(outFS); + } + + @Override + protected void writeProperties(POIFSFileSystem outFS, List<String> writtenEntries) throws IOException { + getSlideShowImpl().writePropertiesImpl(outFS, writtenEntries); + } + + @Override + protected void validateInPlaceWritePossible() throws IllegalStateException { + getSlideShowImpl().validateInPlaceWritePossibleImpl(); + } + + @Override + public DirectoryNode getDirectory() { + return getSlideShowImpl().getDirectory(); + } + + @Override + protected void clearDirectory() { + getSlideShowImpl().clearDirectoryImpl(); + } + + @Override + protected boolean initDirectory() { + return getSlideShowImpl().initDirectoryImpl(); + } + + @Override + protected void replaceDirectory(DirectoryNode newDirectory) throws IOException { + getSlideShowImpl().replaceDirectoryImpl(newDirectory); + } + + @Override + protected String getEncryptedPropertyStreamName() { + return getSlideShowImpl().getEncryptedPropertyStreamName(); + } + + @Override + public EncryptionInfo getEncryptionInfo() { + return getSlideShowImpl().getEncryptionInfo(); + } + + static EscherBSERecord addNewEscherBseRecord(EscherContainerRecord blipStore, PictureType type, byte[] imageData, int offset) { + EscherBSERecord record = new EscherBSERecord(); + record.setRecordId(EscherBSERecord.RECORD_ID); + record.setOptions((short) (0x0002 | (type.nativeId << 4))); + record.setSize(imageData.length + HSLFPictureData.PREAMBLE_SIZE); + record.setUid(Arrays.copyOf(imageData, HSLFPictureData.CHECKSUM_SIZE)); + + record.setBlipTypeMacOS((byte) type.nativeId); + record.setBlipTypeWin32((byte) type.nativeId); + + if (type == PictureType.EMF) { + record.setBlipTypeMacOS((byte) PictureType.PICT.nativeId); + } else if (type == PictureType.WMF) { + record.setBlipTypeMacOS((byte) PictureType.PICT.nativeId); + } else if (type == PictureType.PICT) { + record.setBlipTypeWin32((byte) PictureType.WMF.nativeId); + } + + record.setOffset(offset); + + blipStore.addChildRecord(record); + int count = blipStore.getChildCount(); + blipStore.setOptions((short) ((count << 4) | 0xF)); + + return record; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java index 42682f550d..56d1e5440c 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java @@ -106,7 +106,7 @@ public class HSLFSlideShowEncrypted implements Closeable { Integer encOffset = ptr.getSlideLocationsLookup().get(userEditAtomWithEncryption.getEncryptSessionPersistIdRef()); if (encOffset == null) { // encryption info doesn't exist anymore - // SoftMaker Freeoffice produces such invalid files - check for "SMNativeObjData" ole stream + // SoftMaker Freeoffice produces such invalid files - check for "SMNativeObjData" ole stream dea = null; return; } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java index 62a9d997b1..cc311a1f63 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java @@ -232,10 +232,10 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { // <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> + // <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>> + // <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 @@ -892,7 +892,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { return offset; } - /* ******************* fetching methods follow ********************* */ + /* ******************* fetching methods follow ********************* */ /** diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextRun.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextRun.java index 2ffd690264..f69ee6e432 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextRun.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextRun.java @@ -46,104 +46,104 @@ import org.apache.poi.sl.usermodel.TextShape; */ @SuppressWarnings({"WeakerAccess", "Duplicates", "unused"}) public final class HSLFTextRun implements TextRun { - private static final Logger LOG = LogManager.getLogger(HSLFTextRun.class); - - /** The TextRun we belong to */ - private HSLFTextParagraph parentParagraph; - private String _runText = ""; - /** Caches the font info objects until the text runs are attached to the container */ - private HSLFFontInfo[] cachedFontInfo; - private HSLFHyperlink link; - - /** - * Our paragraph and character style. - * Note - we may share these styles with other RichTextRuns - */ - private TextPropCollection characterStyle = new TextPropCollection(1, TextPropType.character); - - /** - * Create a new wrapper around a rich text string - * @param parentParagraph the parent paragraph - */ - public HSLFTextRun(HSLFTextParagraph parentParagraph) { - this.parentParagraph = parentParagraph; - } - - public TextPropCollection getCharacterStyle() { - return characterStyle; - } - - public void setCharacterStyle(TextPropCollection characterStyle) { - this.characterStyle = characterStyle.copy(); - this.characterStyle.updateTextSize(_runText.length()); - } - - /** - * Supply the SlideShow we belong to - */ - public void updateSheet() { - if (cachedFontInfo != null) { - for (FontGroup tt : FontGroup.values()) { - setFontInfo(cachedFontInfo[tt.ordinal()], tt); - } - cachedFontInfo = null; - } - } - - /** - * Get the length of the text - */ - public int getLength() { - return _runText.length(); - } - - /** - * Fetch the text, in raw storage form - */ - @Override + private static final Logger LOG = LogManager.getLogger(HSLFTextRun.class); + + /** The TextRun we belong to */ + private HSLFTextParagraph parentParagraph; + private String _runText = ""; + /** Caches the font info objects until the text runs are attached to the container */ + private HSLFFontInfo[] cachedFontInfo; + private HSLFHyperlink link; + + /** + * Our paragraph and character style. + * Note - we may share these styles with other RichTextRuns + */ + private TextPropCollection characterStyle = new TextPropCollection(1, TextPropType.character); + + /** + * Create a new wrapper around a rich text string + * @param parentParagraph the parent paragraph + */ + public HSLFTextRun(HSLFTextParagraph parentParagraph) { + this.parentParagraph = parentParagraph; + } + + public TextPropCollection getCharacterStyle() { + return characterStyle; + } + + public void setCharacterStyle(TextPropCollection characterStyle) { + this.characterStyle = characterStyle.copy(); + this.characterStyle.updateTextSize(_runText.length()); + } + + /** + * Supply the SlideShow we belong to + */ + public void updateSheet() { + if (cachedFontInfo != null) { + for (FontGroup tt : FontGroup.values()) { + setFontInfo(cachedFontInfo[tt.ordinal()], tt); + } + cachedFontInfo = null; + } + } + + /** + * Get the length of the text + */ + public int getLength() { + return _runText.length(); + } + + /** + * Fetch the text, in raw storage form + */ + @Override public String getRawText() { - return _runText; - } + return _runText; + } - /** - * Change the text - */ - @Override + /** + * Change the text + */ + @Override public void setText(String text) { - if (text == null) { - throw new HSLFException("text must not be null"); - } - String newText = HSLFTextParagraph.toInternalString(text); - if (!newText.equals(_runText)) { - _runText = newText; - if (HSLFSlideShow.getLoadSavePhase() == HSLFSlideShow.LoadSavePhase.LOADED) { - parentParagraph.setDirty(); - } - } - } - - // --------------- Internal helpers on rich text properties ------- - - /** - * Fetch the value of the given flag in the CharFlagsTextProp. - * Returns false if the CharFlagsTextProp isn't present, since the - * text property won't be set if there's no CharFlagsTextProp. - */ - private boolean isCharFlagsTextPropVal(int index) { - return getFlag(index); - } - - boolean getFlag(int index) { - BitMaskTextProp prop = (characterStyle == null) ? null : characterStyle.findByName(CharFlagsTextProp.NAME); - - if (prop == null || !prop.getSubPropMatches()[index]) { - prop = getMasterProp(); - } - - return prop != null && prop.getSubValue(index); - } - - private <T extends TextProp> T getMasterProp() { + if (text == null) { + throw new HSLFException("text must not be null"); + } + String newText = HSLFTextParagraph.toInternalString(text); + if (!newText.equals(_runText)) { + _runText = newText; + if (HSLFSlideShow.getLoadSavePhase() == HSLFSlideShow.LoadSavePhase.LOADED) { + parentParagraph.setDirty(); + } + } + } + + // --------------- Internal helpers on rich text properties ------- + + /** + * Fetch the value of the given flag in the CharFlagsTextProp. + * Returns false if the CharFlagsTextProp isn't present, since the + * text property won't be set if there's no CharFlagsTextProp. + */ + private boolean isCharFlagsTextPropVal(int index) { + return getFlag(index); + } + + boolean getFlag(int index) { + BitMaskTextProp prop = (characterStyle == null) ? null : characterStyle.findByName(CharFlagsTextProp.NAME); + + if (prop == null || !prop.getSubPropMatches()[index]) { + prop = getMasterProp(); + } + + return prop != null && prop.getSubValue(index); + } + + private <T extends TextProp> T getMasterProp() { final int txtype = parentParagraph.getRunType(); final HSLFSheet sheet = parentParagraph.getSheet(); if (sheet == null) { @@ -160,152 +160,152 @@ public final class HSLFTextRun implements TextRun { String name = CharFlagsTextProp.NAME; final TextPropCollection col = master.getPropCollection(txtype, parentParagraph.getIndentLevel(), name, true); return (col == null) ? null : col.findByName(name); - } - - - /** - * Set the value of the given flag in the CharFlagsTextProp, adding - * it if required. - */ - private void setCharFlagsTextPropVal(int index, boolean value) { - // TODO: check if paragraph/chars can be handled the same ... - if (getFlag(index) != value) { - setFlag(index, value); - parentParagraph.setDirty(); - } - } - - /** - * Sets the value of the given Paragraph TextProp, add if required - * @param propName The name of the Paragraph TextProp - * @param val The value to set for the TextProp - */ - public void setCharTextPropVal(String propName, Integer val) { - getTextParagraph().setPropVal(characterStyle, propName, val); - } - - - // --------------- Friendly getters / setters on rich text properties ------- - - @Override - public boolean isBold() { - return isCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX); - } - - @Override - public void setBold(boolean bold) { - setCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX, bold); - } - - @Override - public boolean isItalic() { - return isCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX); - } - - @Override - public void setItalic(boolean italic) { - setCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX, italic); - } - - @Override - public boolean isUnderlined() { - return isCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX); - } - - @Override - public void setUnderlined(boolean underlined) { - setCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX, underlined); - } - - /** - * Does the text have a shadow? - */ - public boolean isShadowed() { - return isCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX); - } - - /** - * Does the text have a shadow? - */ - public void setShadowed(boolean flag) { - setCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX, flag); - } - - /** - * Is this text embossed? - */ - public boolean isEmbossed() { - return isCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX); - } - - /** - * Is this text embossed? - */ - public void setEmbossed(boolean flag) { - setCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX, flag); - } - - @Override - public boolean isStrikethrough() { - return isCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX); - } - - @Override - public void setStrikethrough(boolean flag) { - setCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX, flag); - } - - /** - * Gets the subscript/superscript option - * - * @return the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript - */ - public int getSuperscript() { - TextProp tp = getTextParagraph().getPropVal(characterStyle, "superscript"); - return tp == null ? 0 : tp.getValue(); - } - - /** - * Sets the subscript/superscript option - * - * @param val the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript - */ - public void setSuperscript(int val) { - setCharTextPropVal("superscript", val); - } + } + + + /** + * Set the value of the given flag in the CharFlagsTextProp, adding + * it if required. + */ + private void setCharFlagsTextPropVal(int index, boolean value) { + // TODO: check if paragraph/chars can be handled the same ... + if (getFlag(index) != value) { + setFlag(index, value); + parentParagraph.setDirty(); + } + } + + /** + * Sets the value of the given Paragraph TextProp, add if required + * @param propName The name of the Paragraph TextProp + * @param val The value to set for the TextProp + */ + public void setCharTextPropVal(String propName, Integer val) { + getTextParagraph().setPropVal(characterStyle, propName, val); + } + + + // --------------- Friendly getters / setters on rich text properties ------- + + @Override + public boolean isBold() { + return isCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX); + } + + @Override + public void setBold(boolean bold) { + setCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX, bold); + } + + @Override + public boolean isItalic() { + return isCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX); + } + + @Override + public void setItalic(boolean italic) { + setCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX, italic); + } + + @Override + public boolean isUnderlined() { + return isCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX); + } + + @Override + public void setUnderlined(boolean underlined) { + setCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX, underlined); + } + + /** + * Does the text have a shadow? + */ + public boolean isShadowed() { + return isCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX); + } + + /** + * Does the text have a shadow? + */ + public void setShadowed(boolean flag) { + setCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX, flag); + } + + /** + * Is this text embossed? + */ + public boolean isEmbossed() { + return isCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX); + } + + /** + * Is this text embossed? + */ + public void setEmbossed(boolean flag) { + setCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX, flag); + } + + @Override + public boolean isStrikethrough() { + return isCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX); + } @Override - public Double getFontSize() { + public void setStrikethrough(boolean flag) { + setCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX, flag); + } + + /** + * Gets the subscript/superscript option + * + * @return the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript + */ + public int getSuperscript() { + TextProp tp = getTextParagraph().getPropVal(characterStyle, "superscript"); + return tp == null ? 0 : tp.getValue(); + } + + /** + * Sets the subscript/superscript option + * + * @param val the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript + */ + public void setSuperscript(int val) { + setCharTextPropVal("superscript", val); + } + + @Override + public Double getFontSize() { TextProp tp = getTextParagraph().getPropVal(characterStyle, "font.size"); return tp == null ? null : (double)tp.getValue(); - } + } - @Override - public void setFontSize(Double fontSize) { - Integer iFontSize = (fontSize == null) ? null : fontSize.intValue(); - setCharTextPropVal("font.size", iFontSize); - } + @Override + public void setFontSize(Double fontSize) { + Integer iFontSize = (fontSize == null) ? null : fontSize.intValue(); + setCharTextPropVal("font.size", iFontSize); + } - /** - * Gets the font index - */ - public int getFontIndex() { + /** + * Gets the font index + */ + public int getFontIndex() { TextProp tp = getTextParagraph().getPropVal(characterStyle, "font.index"); return tp == null ? -1 : tp.getValue(); - } + } - /** - * Sets the font index - */ - public void setFontIndex(int idx) { - setCharTextPropVal("font.index", idx); - } + /** + * Sets the font index + */ + public void setFontIndex(int idx) { + setCharTextPropVal("font.index", idx); + } - @Override - public void setFontFamily(String typeface) { - setFontFamily(typeface, FontGroup.LATIN); - } + @Override + public void setFontFamily(String typeface) { + setFontFamily(typeface, FontGroup.LATIN); + } @Override public void setFontFamily(String typeface, FontGroup fontGroup) { @@ -313,7 +313,7 @@ public final class HSLFTextRun implements TextRun { } @Override - public void setFontInfo(FontInfo fontInfo, FontGroup fontGroup) { + public void setFontInfo(FontInfo fontInfo, FontGroup fontGroup) { FontGroup fg = safeFontGroup(fontGroup); HSLFSheet sheet = parentParagraph.getSheet(); @@ -352,14 +352,14 @@ public final class HSLFTextRun implements TextRun { } - setCharTextPropVal("font.index", fontIdx); + setCharTextPropVal("font.index", fontIdx); setCharTextPropVal(propName, fontIdx); } @Override - public String getFontFamily() { + public String getFontFamily() { return getFontFamily(null); - } + } @Override public String getFontFamily(FontGroup fontGroup) { @@ -367,58 +367,58 @@ public final class HSLFTextRun implements TextRun { return (fi != null) ? fi.getTypeface() : null; } - @Override - public HSLFFontInfo getFontInfo(final FontGroup fontGroup) { + @Override + public HSLFFontInfo getFontInfo(final FontGroup fontGroup) { FontGroup fg = safeFontGroup(fontGroup); - HSLFSheet sheet = parentParagraph.getSheet(); + HSLFSheet sheet = parentParagraph.getSheet(); @SuppressWarnings("resource") HSLFSlideShow slideShow = (sheet == null) ? null : sheet.getSlideShow(); - if (sheet == null || slideShow == null) { - return (cachedFontInfo != null) ? cachedFontInfo[fg.ordinal()] : null; - } - - String propName; - switch (fg) { - default: - case LATIN: - propName = "font.index,ansi.font.index"; - break; + if (sheet == null || slideShow == null) { + return (cachedFontInfo != null) ? cachedFontInfo[fg.ordinal()] : null; + } + + String propName; + switch (fg) { + default: + case LATIN: + propName = "font.index,ansi.font.index"; + break; case COMPLEX_SCRIPT: - case EAST_ASIAN: - propName = "asian.font.index"; - break; + case EAST_ASIAN: + propName = "asian.font.index"; + break; case SYMBOL: - propName = "symbol.font.index"; - break; - } + propName = "symbol.font.index"; + break; + } TextProp tp = getTextParagraph().getPropVal(characterStyle, propName); - return (tp != null) ? slideShow.getFont(tp.getValue()) : null; - } - - /** - * @return font color as PaintStyle - */ - @Override - public SolidPaint getFontColor() { - TextProp tp = getTextParagraph().getPropVal(characterStyle, "font.color"); - if (tp == null) { + return (tp != null) ? slideShow.getFont(tp.getValue()) : null; + } + + /** + * @return font color as PaintStyle + */ + @Override + public SolidPaint getFontColor() { + TextProp tp = getTextParagraph().getPropVal(characterStyle, "font.color"); + if (tp == null) { return null; } - Color color = HSLFTextParagraph.getColorFromColorIndexStruct(tp.getValue(), parentParagraph.getSheet()); + Color color = HSLFTextParagraph.getColorFromColorIndexStruct(tp.getValue(), parentParagraph.getSheet()); return DrawPaint.createSolidPaint(color); - } + } - /** - * Sets color of the text, as a int bgr. - * (PowerPoint stores as BlueGreenRed, not the more - * usual RedGreenBlue) - * @see Color - */ - public void setFontColor(int bgr) { - setCharTextPropVal("font.color", bgr); - } + /** + * Sets color of the text, as a int bgr. + * (PowerPoint stores as BlueGreenRed, not the more + * usual RedGreenBlue) + * @see Color + */ + public void setFontColor(int bgr) { + setCharTextPropVal("font.color", bgr); + } @Override @@ -426,17 +426,17 @@ public final class HSLFTextRun implements TextRun { setFontColor(DrawPaint.createSolidPaint(color)); } - @Override - public void setFontColor(PaintStyle color) { - if (!(color instanceof SolidPaint)) { - throw new IllegalArgumentException("HSLF only supports solid paint"); - } - // In PowerPont RGB bytes are swapped, as BGR - SolidPaint sp = (SolidPaint)color; - Color c = DrawPaint.applyColorTransform(sp.getSolidColor()); - int rgb = new Color(c.getBlue(), c.getGreen(), c.getRed(), 254).getRGB(); - setFontColor(rgb); - } + @Override + public void setFontColor(PaintStyle color) { + if (!(color instanceof SolidPaint)) { + throw new IllegalArgumentException("HSLF only supports solid paint"); + } + // In PowerPont RGB bytes are swapped, as BGR + SolidPaint sp = (SolidPaint)color; + Color c = DrawPaint.applyColorTransform(sp.getSolidColor()); + int rgb = new Color(c.getBlue(), c.getGreen(), c.getRed(), 254).getRGB(); + setFontColor(rgb); + } private void setFlag(int index, boolean value) { BitMaskTextProp prop = characterStyle.addWithName(CharFlagsTextProp.NAME); @@ -525,8 +525,8 @@ public final class HSLFTextRun implements TextRun { return (fontGroup != null) ? fontGroup : FontGroup.getFontGroupFirst(getRawText()); } - @Override - public HSLFTextParagraph getParagraph() { - return parentParagraph; - } + @Override + public HSLFTextParagraph getParagraph() { + return parentParagraph; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/util/SystemTimeUtils.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/util/SystemTimeUtils.java index 10b566a8be..151ceff1c7 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/util/SystemTimeUtils.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/util/SystemTimeUtils.java @@ -34,16 +34,16 @@ import org.apache.poi.util.LocaleUtil; * stored as UTC either, but rather the local system time (yuck.) */ public final class SystemTimeUtils { - /** - * Get the date found in the byte array, as a java Data object - */ - public static Date getDate(byte[] data) { - return getDate(data,0); - } - /** - * Get the date found in the byte array, as a java Data object - */ - public static Date getDate(byte[] data, int offset) { + /** + * Get the date found in the byte array, as a java Data object + */ + public static Date getDate(byte[] data) { + return getDate(data,0); + } + /** + * Get the date found in the byte array, as a java Data object + */ + public static Date getDate(byte[] data, int offset) { Calendar cal = LocaleUtil.getLocaleCalendar(); cal.set(Calendar.YEAR, LittleEndian.getShort(data,offset)); @@ -57,20 +57,20 @@ public final class SystemTimeUtils { cal.set(Calendar.MILLISECOND, LittleEndian.getShort(data,offset+14)); return cal.getTime(); - } + } - /** - * Convert the supplied java Date into a SystemTime struct, and write it - * into the supplied byte array. - */ - public static void storeDate(Date date, byte[] dest) { - storeDate(date, dest, 0); - } - /** - * Convert the supplied java Date into a SystemTime struct, and write it - * into the supplied byte array. - */ - public static void storeDate(Date date, byte[] dest, int offset) { + /** + * Convert the supplied java Date into a SystemTime struct, and write it + * into the supplied byte array. + */ + public static void storeDate(Date date, byte[] dest) { + storeDate(date, dest, 0); + } + /** + * Convert the supplied java Date into a SystemTime struct, and write it + * into the supplied byte array. + */ + public static void storeDate(Date date, byte[] dest, int offset) { Calendar cal = LocaleUtil.getLocaleCalendar(); cal.setTime(date); @@ -82,5 +82,5 @@ public final class SystemTimeUtils { LittleEndian.putShort(dest, offset + 10,(short) cal.get(Calendar.MINUTE)); LittleEndian.putShort(dest, offset + 12,(short) cal.get(Calendar.SECOND)); LittleEndian.putShort(dest, offset + 14,(short) cal.get(Calendar.MILLISECOND)); - } + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/PropertiesChunk.java b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/PropertiesChunk.java index 7915ca5c66..377dec1615 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/PropertiesChunk.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/PropertiesChunk.java @@ -357,7 +357,7 @@ public abstract class PropertiesChunk extends Chunk { } // generic header // page 23, point 2.4.2 - // tag is the property id and its type + // tag is the property id and its type long tag = Long.parseLong(getFileName(property, value.getActualType()), 16); LittleEndian.putUInt(tag, out); LittleEndian.putUInt(value.getFlags(), out); // readable + writable diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java index 9f00435369..8a81a55c96 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java @@ -18,12 +18,12 @@ package org.apache.poi.hsmf.exceptions; public final class ChunkNotFoundException extends Exception { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public ChunkNotFoundException() { - super("Chunk not found"); - } - public ChunkNotFoundException(String chunkName) { - super(chunkName + " was named, but not found in POIFS object"); - } + public ChunkNotFoundException() { + super("Chunk not found"); + } + public ChunkNotFoundException(String chunkName) { + super(chunkName + " was named, but not found in POIFS object"); + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/AbstractWordUtils.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/AbstractWordUtils.java index 1f633c5767..9aaa892017 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/AbstractWordUtils.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/AbstractWordUtils.java @@ -428,7 +428,7 @@ public class AbstractWordUtils { if ( format != 0 ) - LOG.atInfo().log("NYI: toListItemNumberLabel(): {}", box(format)); + LOG.atInfo().log("NYI: toListItemNumberLabel(): {}", box(format)); return String.valueOf( number ); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/extractor/Word6Extractor.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/extractor/Word6Extractor.java index 2cd17399e3..8252d681be 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/extractor/Word6Extractor.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/extractor/Word6Extractor.java @@ -35,16 +35,16 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; * with HWPF. */ public final class Word6Extractor implements POIOLE2TextExtractor { - private HWPFOldDocument doc; - private boolean doCloseFilesystem = true; + private HWPFOldDocument doc; + private boolean doCloseFilesystem = true; - /** - * Create a new Word Extractor - * @param is InputStream containing the word file - */ - public Word6Extractor(InputStream is) throws IOException { - this( new POIFSFileSystem(is) ); - } + /** + * Create a new Word Extractor + * @param is InputStream containing the word file + */ + public Word6Extractor(InputStream is) throws IOException { + this( new POIFSFileSystem(is) ); + } /** * Create a new Word Extractor @@ -68,42 +68,42 @@ public final class Word6Extractor implements POIOLE2TextExtractor { this( new HWPFOldDocument( dir ) ); } - /** - * Create a new Word Extractor - * @param doc The HWPFOldDocument to extract from - */ - public Word6Extractor(HWPFOldDocument doc) { - this.doc = doc; - } + /** + * Create a new Word Extractor + * @param doc The HWPFOldDocument to extract from + */ + public Word6Extractor(HWPFOldDocument doc) { + this.doc = doc; + } /** * Get the text from the word file, as an array with one String * per paragraph */ - @Deprecated - public String[] getParagraphText() { - String[] ret; + @Deprecated + public String[] getParagraphText() { + String[] ret; - // Extract using the model code - try { - Range r = doc.getRange(); + // Extract using the model code + try { + Range r = doc.getRange(); - ret = WordExtractor.getParagraphText(r); - } catch (Exception e) { + ret = WordExtractor.getParagraphText(r); + } catch (Exception e) { // Something's up with turning the text pieces into paragraphs // Fall back to ripping out the text pieces - ret = new String[doc.getTextTable().getTextPieces().size()]; - for(int i=0; i<ret.length; i++) { - ret[i] = doc.getTextTable().getTextPieces().get(i).getStringBuilder().toString(); - - // Fix the line endings - ret[i] = ret[i].replaceAll("\r", "\ufffe"); - ret[i] = ret[i].replaceAll("\ufffe","\r\n"); - } - } - - return ret; - } + ret = new String[doc.getTextTable().getTextPieces().size()]; + for(int i=0; i<ret.length; i++) { + ret[i] = doc.getTextTable().getTextPieces().get(i).getStringBuilder().toString(); + + // Fix the line endings + ret[i] = ret[i].replaceAll("\r", "\ufffe"); + ret[i] = ret[i].replaceAll("\ufffe","\r\n"); + } + } + + return ret; + } public String getText() { try { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/BytePropertyNode.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/BytePropertyNode.java index 9ad54d7d9c..2c53c375de 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/BytePropertyNode.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/BytePropertyNode.java @@ -54,7 +54,7 @@ public abstract class BytePropertyNode<T extends BytePropertyNode<T>> extends Pr * use char positions for all operations. Including save * operations, because only char positions are preserved. */ - @Deprecated + @Deprecated public int getStartBytes() { return startBytes; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/CHPBinTable.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/CHPBinTable.java index 24cfb6d183..1d0a570791 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/CHPBinTable.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/CHPBinTable.java @@ -384,11 +384,11 @@ public class CHPBinTable CHPX chpx = _textRuns.get(listIndex); if (chpx.getStart() < cpStart) { - // Copy the properties of the one before to afterwards - // Will go: - // Original, until insert at point - // New one - // Clone of original, on to the old end + // Copy the properties of the one before to afterwards + // Will go: + // Original, until insert at point + // New one + // Clone of original, on to the old end CHPX clone = new CHPX(0, 0, chpx.getSprmBuf()); // Again ensure contains character based offsets no matter what clone.setStart(cpStart); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/Ffn.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/Ffn.java index 32d9631277..559e1af71e 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/Ffn.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/Ffn.java @@ -98,22 +98,22 @@ public final class Ffn public short getWeight() { - return _wWeight; + return _wWeight; } public byte getChs() { - return _chs; + return _chs; } public byte [] getPanose() { - return _panose; + return _panose; } public byte [] getFontSig() { - return _fontSig; + return _fontSig; } public int getSize() diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/FileInformationBlock.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/FileInformationBlock.java index ecb125b6e8..37ed665ed4 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/FileInformationBlock.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/FileInformationBlock.java @@ -688,13 +688,13 @@ public final class FileInformationBlock { * i.e. lcbPlcfHdd */ public int getPlcfHddSize() { - return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFHDD); + return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFHDD); } public void setPlcfHddOffset(int fcPlcfHdd) { - _fieldHandler.setFieldOffset(FIBFieldHandler.PLCFHDD, fcPlcfHdd); + _fieldHandler.setFieldOffset(FIBFieldHandler.PLCFHDD, fcPlcfHdd); } public void setPlcfHddSize(int lcbPlcfHdd) { - _fieldHandler.setFieldSize(FIBFieldHandler.PLCFHDD, lcbPlcfHdd); + _fieldHandler.setFieldSize(FIBFieldHandler.PLCFHDD, lcbPlcfHdd); } public int getFcSttbSavedBy() diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/ListLevel.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/ListLevel.java index f13e9a3884..39c0628487 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/ListLevel.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/ListLevel.java @@ -189,7 +189,7 @@ public final class ListLevel * the numbering does not restart or {@code -1} if no restart is applicable */ public short getRestart() { - return _lvlf.isFNoRestart() ? _lvlf.getIlvlRestartLim() : -1; + return _lvlf.isFNoRestart() ? _lvlf.getIlvlRestartLim() : -1; } /** @@ -202,7 +202,7 @@ public final class ListLevel * significant levels must be overridden; {@code false} otherwise */ public boolean isLegalNumbering() { - return _lvlf.isFLegal(); + return _lvlf.isFLegal(); } /** @@ -213,7 +213,7 @@ public final class ListLevel * @return {@code 0}-terminated array, unless it is full */ public byte[] getLevelNumberingPlaceholderOffsets() { - return _lvlf.getRgbxchNums(); + return _lvlf.getRgbxchNums(); } int read( final byte[] data, final int startOffset ) diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/ListTables.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/ListTables.java index 3903b04a77..1ae1679046 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/ListTables.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/ListTables.java @@ -150,7 +150,7 @@ public final class ListTables return lst.getLevels()[level]; } LOGGER.atWarn().log("Requested level {} which was greater than the maximum defined ({})", box(level),box(lst.numLevels())); - return null; + return null; } public ListData getListData(int lsid) diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/OfficeArtContent.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/OfficeArtContent.java index df53ee6bc4..d8c13132b7 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/OfficeArtContent.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/OfficeArtContent.java @@ -38,82 +38,82 @@ import static org.apache.logging.log4j.util.Unbox.box; @Internal public final class OfficeArtContent { - /** - * {@link EscherRecordTypes#DGG_CONTAINER} containing drawing group information for the document. - */ - private final EscherContainerRecord drawingGroupData = new EscherContainerRecord(); - - /** - * {@link EscherRecordTypes#DG_CONTAINER} for drawings in the Main Document. - * <p> - * {@code null} to indicate that the document does not have a {@link EscherRecordTypes#DG_CONTAINER} for the Main - * Document. - */ - private EscherContainerRecord mainDocumentDgContainer; - - /** - * {@link EscherRecordTypes#DG_CONTAINER} for drawings in the Header Document. - * <p> - * {@code null} to indicate that the document does not have a {@link EscherRecordTypes#DG_CONTAINER} for the Header - * Document. - */ - private EscherContainerRecord headerDocumentDgContainer; - - public OfficeArtContent(byte[] data, int offset, int size) { - fillEscherRecords(data, offset, size); - } - - /** - * Parses the records out of the given data. - * - * The thing to be aware of here is that if {@code size} is {@code 0}, the document does not contain images. - * - * @see FileInformationBlock#getLcbDggInfo() - */ - private void fillEscherRecords(byte[] data, int offset, int size) { - if (size == 0) return; - - EscherRecordFactory recordFactory = new DefaultEscherRecordFactory(); - int pos = offset; - pos += drawingGroupData.fillFields(data, pos, recordFactory); - assert drawingGroupData.getRecordId() == EscherRecordTypes.DGG_CONTAINER.typeID; - - /* - * After the drawingGroupData there is an array (2 slots max) that has data about drawings. According to the - * spec, the first slot is for the Main Document, the second for the Header Document. Additionally, the - * OfficeArtWordDrawing structure has a byte (dgglbl) that indicates whether the structure is for the Main or - * Header Document. In practice we've seen documents such as 61911.doc where the order of array entries does not - * match the dgglbl byte. As the byte is more likely to be reliable, we base the parsing off of that rather than - * array order. - */ - - // This should loop at most twice - while (pos < offset + size) { - - // Named this way to match section 2.9.172 of [MS-DOC] - v20191119. - byte dgglbl = data[pos]; - assert dgglbl == 0x00 || dgglbl == 0x01; - pos++; - - EscherContainerRecord dgContainer = new EscherContainerRecord(); - pos+= dgContainer.fillFields(data, pos, recordFactory); - assert dgContainer.getRecordId() == EscherRecordTypes.DG_CONTAINER.typeID; - - switch (dgglbl) { - case 0x00: - mainDocumentDgContainer = dgContainer; - break; - case 0x01: - headerDocumentDgContainer = dgContainer; - break; - default: - LogManager.getLogger(OfficeArtContent.class).atWarn() - .log("dgglbl {} for OfficeArtWordDrawing is out of bounds [0, 1]", box(dgglbl)); - } - } - - assert pos == offset + size; - } + /** + * {@link EscherRecordTypes#DGG_CONTAINER} containing drawing group information for the document. + */ + private final EscherContainerRecord drawingGroupData = new EscherContainerRecord(); + + /** + * {@link EscherRecordTypes#DG_CONTAINER} for drawings in the Main Document. + * <p> + * {@code null} to indicate that the document does not have a {@link EscherRecordTypes#DG_CONTAINER} for the Main + * Document. + */ + private EscherContainerRecord mainDocumentDgContainer; + + /** + * {@link EscherRecordTypes#DG_CONTAINER} for drawings in the Header Document. + * <p> + * {@code null} to indicate that the document does not have a {@link EscherRecordTypes#DG_CONTAINER} for the Header + * Document. + */ + private EscherContainerRecord headerDocumentDgContainer; + + public OfficeArtContent(byte[] data, int offset, int size) { + fillEscherRecords(data, offset, size); + } + + /** + * Parses the records out of the given data. + * + * The thing to be aware of here is that if {@code size} is {@code 0}, the document does not contain images. + * + * @see FileInformationBlock#getLcbDggInfo() + */ + private void fillEscherRecords(byte[] data, int offset, int size) { + if (size == 0) return; + + EscherRecordFactory recordFactory = new DefaultEscherRecordFactory(); + int pos = offset; + pos += drawingGroupData.fillFields(data, pos, recordFactory); + assert drawingGroupData.getRecordId() == EscherRecordTypes.DGG_CONTAINER.typeID; + + /* + * After the drawingGroupData there is an array (2 slots max) that has data about drawings. According to the + * spec, the first slot is for the Main Document, the second for the Header Document. Additionally, the + * OfficeArtWordDrawing structure has a byte (dgglbl) that indicates whether the structure is for the Main or + * Header Document. In practice we've seen documents such as 61911.doc where the order of array entries does not + * match the dgglbl byte. As the byte is more likely to be reliable, we base the parsing off of that rather than + * array order. + */ + + // This should loop at most twice + while (pos < offset + size) { + + // Named this way to match section 2.9.172 of [MS-DOC] - v20191119. + byte dgglbl = data[pos]; + assert dgglbl == 0x00 || dgglbl == 0x01; + pos++; + + EscherContainerRecord dgContainer = new EscherContainerRecord(); + pos+= dgContainer.fillFields(data, pos, recordFactory); + assert dgContainer.getRecordId() == EscherRecordTypes.DG_CONTAINER.typeID; + + switch (dgglbl) { + case 0x00: + mainDocumentDgContainer = dgContainer; + break; + case 0x01: + headerDocumentDgContainer = dgContainer; + break; + default: + LogManager.getLogger(OfficeArtContent.class).atWarn() + .log("dgglbl {} for OfficeArtWordDrawing is out of bounds [0, 1]", box(dgglbl)); + } + } + + assert pos == offset + size; + } private List<? extends EscherContainerRecord> getDgContainers() { List<EscherContainerRecord> dgContainers = new ArrayList<>(2); @@ -126,11 +126,11 @@ public final class OfficeArtContent { return dgContainers; } - /** - * @return The {@link EscherRecordTypes#BSTORE_CONTAINER} or {@code null} if the document doesn't have one. - */ - public EscherContainerRecord getBStoreContainer() { - return drawingGroupData.getChildById(EscherRecordTypes.BSTORE_CONTAINER.typeID); + /** + * @return The {@link EscherRecordTypes#BSTORE_CONTAINER} or {@code null} if the document doesn't have one. + */ + public EscherContainerRecord getBStoreContainer() { + return drawingGroupData.getChildById(EscherRecordTypes.BSTORE_CONTAINER.typeID); } public List<? extends EscherContainerRecord> getSpgrContainers() @@ -167,12 +167,12 @@ public final class OfficeArtContent { return spContainers; } - @Override - public String toString() { - return "OfficeArtContent{" + - "drawingGroupData=" + drawingGroupData + - ", mainDocumentDgContainer=" + mainDocumentDgContainer + - ", headerDocumentDgContainer=" + headerDocumentDgContainer + - '}'; - } + @Override + public String toString() { + return "OfficeArtContent{" + + "drawingGroupData=" + drawingGroupData + + ", mainDocumentDgContainer=" + mainDocumentDgContainer + + ", headerDocumentDgContainer=" + headerDocumentDgContainer + + '}'; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/RevisionMarkAuthorTable.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/RevisionMarkAuthorTable.java index 3cad305e05..abda3b3557 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/RevisionMarkAuthorTable.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/RevisionMarkAuthorTable.java @@ -31,61 +31,61 @@ import org.apache.poi.util.Internal; */ @Internal public final class RevisionMarkAuthorTable { - /** - * Array of entries. - */ - private String[] entries; + /** + * Array of entries. + */ + private String[] entries; - /** - * Constructor to read the table from the table stream. - * - * @param tableStream the table stream. - * @param offset the offset into the byte array. - * @param size the size of the table in the byte array. - */ + /** + * Constructor to read the table from the table stream. + * + * @param tableStream the table stream. + * @param offset the offset into the byte array. + * @param size the size of the table in the byte array. + */ public RevisionMarkAuthorTable( byte[] tableStream, int offset, int size ) throws IOException { entries = SttbUtils.readSttbfRMark( tableStream, offset ); } - /** - * Gets the entries. The returned list cannot be modified. - * - * @return the list of entries. - */ - public List<String> getEntries() { - return Collections.unmodifiableList(Arrays.asList(entries)); - } + /** + * Gets the entries. The returned list cannot be modified. + * + * @return the list of entries. + */ + public List<String> getEntries() { + return Collections.unmodifiableList(Arrays.asList(entries)); + } - /** - * Get an author by its index. Returns null if it does not exist. - * - * @return the revision mark author - */ - public String getAuthor(int index) { - String auth = null; - if(index >= 0 && index < entries.length) { - auth = entries[index]; - } - return auth; - } + /** + * Get an author by its index. Returns null if it does not exist. + * + * @return the revision mark author + */ + public String getAuthor(int index) { + String auth = null; + if(index >= 0 && index < entries.length) { + auth = entries[index]; + } + return auth; + } - /** - * Gets the number of entries. - * - * @return the number of entries. - */ - public int getSize() { - return entries.length; - } + /** + * Gets the number of entries. + * + * @return the number of entries. + */ + public int getSize() { + return entries.length; + } - /** - * Writes this table to the table stream. - * - * @param tableStream the table stream to write to. - * @throws IOException if an error occurs while writing. - */ + /** + * Writes this table to the table stream. + * + * @param tableStream the table stream to write to. + * @throws IOException if an error occurs while writing. + */ public void writeTo( ByteArrayOutputStream tableStream ) throws IOException { SttbUtils.writeSttbfRMark( entries, tableStream ); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/TextPiece.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/TextPiece.java index bdb9ba492a..4dada2805b 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/TextPiece.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/TextPiece.java @@ -149,10 +149,10 @@ public class TextPiece extends PropertyNode<TextPiece> { int myEnd = getEnd(); int end = start + length; - /* do we have to delete from this text piece? */ + /* do we have to delete from this text piece? */ if (start <= myEnd && end >= myStart) { - /* find where the deleted area overlaps with this text piece */ + /* find where the deleted area overlaps with this text piece */ int overlapStart = Math.max(myStart, start); int overlapEnd = Math.min(myEnd, end); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/UnhandledDataStructure.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/UnhandledDataStructure.java index 89d5c492fd..3e69c5979a 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/UnhandledDataStructure.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/model/UnhandledDataStructure.java @@ -44,7 +44,7 @@ public final class UnhandledDataStructure if (offset < 0 || length < 0) { throw new IndexOutOfBoundsException("Offset and Length must both be >= 0, negative " + - "indicies are not permitted - code is tried to read " + length + " from offset " + offset); + "indicies are not permitted - code is tried to read " + length + " from offset " + offset); } // Save that requested portion of the data diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/sprm/CharacterSprmUncompressor.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/sprm/CharacterSprmUncompressor.java index bad4429041..372393945e 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/sprm/CharacterSprmUncompressor.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/sprm/CharacterSprmUncompressor.java @@ -217,7 +217,7 @@ public final class CharacterSprmUncompressor extends SprmUncompressor break; case 0xd: - // undocumented + // undocumented break; case 0xe: newCHP.setFcObj (sprm.getOperand()); @@ -689,17 +689,17 @@ public final class CharacterSprmUncompressor extends SprmUncompressor case 0x74: // sprmCRgLid1 break; - case 0x75: - // sprmCFNoProof -- 0x875 - /* - * "A ToggleOperand value that specifies whether the text is excluded from the proofing analysis. By default, text is not excluded from the proofing analysis." - * - * Word (.doc) Binary File Format. Copyright (c) 2012 Microsoft - * Corporation. Released: October 8, 2012 - */ - newCHP.setFNoProof(getCHPFlag((byte) sprm.getOperand(), - oldCHP.isFNoProof())); - break; + case 0x75: + // sprmCFNoProof -- 0x875 + /* + * "A ToggleOperand value that specifies whether the text is excluded from the proofing analysis. By default, text is not excluded from the proofing analysis." + * + * Word (.doc) Binary File Format. Copyright (c) 2012 Microsoft + * Corporation. Released: October 8, 2012 + */ + newCHP.setFNoProof(getCHPFlag((byte) sprm.getOperand(), + oldCHP.isFNoProof())); + break; default: LOG.atDebug().log("Unknown CHP sprm ignored: {}", sprm); break; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/sprm/SprmUncompressor.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/sprm/SprmUncompressor.java index ef2e117ead..453d8b8122 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/sprm/SprmUncompressor.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/sprm/SprmUncompressor.java @@ -42,7 +42,7 @@ public abstract class SprmUncompressor { return true; } - return false; + return false; } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/HeaderStories.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/HeaderStories.java index 8df6f545c7..738253c3d5 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/HeaderStories.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/HeaderStories.java @@ -34,14 +34,14 @@ import org.apache.poi.hwpf.model.SubdocumentType; * as offsets are not yet updated! */ public final class HeaderStories { - private final Range headerStories; - private PlexOfCps plcfHdd; + private final Range headerStories; + private PlexOfCps plcfHdd; - private boolean stripFields; + private boolean stripFields; - public HeaderStories(HWPFDocument doc) { - this.headerStories = doc.getHeaderStoryRange(); - FileInformationBlock fib = doc.getFileInformationBlock(); + public HeaderStories(HWPFDocument doc) { + this.headerStories = doc.getHeaderStoryRange(); + FileInformationBlock fib = doc.getFileInformationBlock(); // // If there's no PlcfHdd, nothing to do // if(fib.getCcpHdd() == 0) { @@ -49,11 +49,11 @@ public final class HeaderStories { // } if (fib.getSubdocumentTextStreamLength( SubdocumentType.HEADER ) == 0) - return; + return; - if(fib.getPlcfHddSize() == 0) { - return; - } + if(fib.getPlcfHddSize() == 0) { + return; + } // Handle the PlcfHdd /* @@ -169,24 +169,24 @@ public final class HeaderStories { /** * @deprecated 3.8 beta 4 */ - @Deprecated - public String getEvenHeader() { - return getAt(6+0); - } - /** + @Deprecated + public String getEvenHeader() { + return getAt(6+0); + } + /** * @deprecated 3.8 beta 4 */ @Deprecated public String getOddHeader() { - return getAt(6+1); - } + return getAt(6+1); + } /** * @deprecated 3.8 beta 4 */ @Deprecated public String getFirstHeader() { - return getAt(6+4); - } + return getAt(6+4); + } public Range getEvenHeaderSubrange() { @@ -199,33 +199,33 @@ public final class HeaderStories { return getSubrangeAt(6+4); } - /** - * Returns the correct, defined header for the given - * one based page - * @param pageNumber The one based page number - */ - public String getHeader(int pageNumber) { - // First page header is optional, only return - // if it's set - if(pageNumber == 1) { + /** + * Returns the correct, defined header for the given + * one based page + * @param pageNumber The one based page number + */ + public String getHeader(int pageNumber) { + // First page header is optional, only return + // if it's set + if(pageNumber == 1) { final String fh = getFirstHeader(); - if(fh != null && !fh.isEmpty()) { - return fh; - } - } - // Even page header is optional, only return - // if it's set - if(pageNumber % 2 == 0) { + if(fh != null && !fh.isEmpty()) { + return fh; + } + } + // Even page header is optional, only return + // if it's set + if(pageNumber % 2 == 0) { final String eh = getEvenHeader(); - if(eh != null && !eh.isEmpty()) { - return eh; - } - } - // Odd is the default - return getOddHeader(); - } - - /** + if(eh != null && !eh.isEmpty()) { + return eh; + } + } + // Odd is the default + return getOddHeader(); + } + + /** * @deprecated 3.8 beta 4 */ @Deprecated @@ -234,7 +234,7 @@ public final class HeaderStories { return getAt( 6 + 2 ); } - /** + /** * @deprecated 3.8 beta 4 */ @Deprecated @@ -267,73 +267,73 @@ public final class HeaderStories { return getSubrangeAt( 6 + 5 ); } - /** - * Returns the correct, defined footer for the given - * one based page - * @param pageNumber The one based page number - */ - public String getFooter(int pageNumber) { - // First page footer is optional, only return - // if it's set - if(pageNumber == 1) { - final String ff = getFirstFooter(); - if(ff != null && !ff.isEmpty()) { - return ff; - } - } - // Even page footer is optional, only return - // if it's set - if(pageNumber % 2 == 0) { - final String ef = getEvenFooter(); - if(ef != null && !ef.isEmpty()) { - return ef; - } - } - // Odd is the default - return getOddFooter(); - } - - - /** - * Get the string that's pointed to by the - * given plcfHdd index - * @deprecated 3.8 beta 4 - */ + /** + * Returns the correct, defined footer for the given + * one based page + * @param pageNumber The one based page number + */ + public String getFooter(int pageNumber) { + // First page footer is optional, only return + // if it's set + if(pageNumber == 1) { + final String ff = getFirstFooter(); + if(ff != null && !ff.isEmpty()) { + return ff; + } + } + // Even page footer is optional, only return + // if it's set + if(pageNumber % 2 == 0) { + final String ef = getEvenFooter(); + if(ef != null && !ef.isEmpty()) { + return ef; + } + } + // Odd is the default + return getOddFooter(); + } + + + /** + * Get the string that's pointed to by the + * given plcfHdd index + * @deprecated 3.8 beta 4 + */ @Deprecated - private String getAt(int plcfHddIndex) { - if(plcfHdd == null) return null; - - GenericPropertyNode prop = plcfHdd.getProperty(plcfHddIndex); - if(prop.getStart() == prop.getEnd()) { - // Empty story - return ""; - } - if(prop.getEnd() < prop.getStart()) { - // Broken properties? - return ""; - } - - // Ensure we're getting a sensible length - String rawText = headerStories.text(); - int start = Math.min(prop.getStart(), rawText.length()); - int end = Math.min(prop.getEnd(), rawText.length()); - - // Grab the contents - String text = rawText.substring(start, end); - - // Strip off fields and macros if requested - if(stripFields) { - return Range.stripFields(text); - } - // If you create a header/footer, then remove it again, word - // will leave \r\r. Turn these back into an empty string, - // which is more what you'd expect - if(text.equals("\r\r")) { - return ""; - } - - return text; - } + private String getAt(int plcfHddIndex) { + if(plcfHdd == null) return null; + + GenericPropertyNode prop = plcfHdd.getProperty(plcfHddIndex); + if(prop.getStart() == prop.getEnd()) { + // Empty story + return ""; + } + if(prop.getEnd() < prop.getStart()) { + // Broken properties? + return ""; + } + + // Ensure we're getting a sensible length + String rawText = headerStories.text(); + int start = Math.min(prop.getStart(), rawText.length()); + int end = Math.min(prop.getEnd(), rawText.length()); + + // Grab the contents + String text = rawText.substring(start, end); + + // Strip off fields and macros if requested + if(stripFields) { + return Range.stripFields(text); + } + // If you create a header/footer, then remove it again, word + // will leave \r\r. Turn these back into an empty string, + // which is more what you'd expect + if(text.equals("\r\r")) { + return ""; + } + + return text; + } private Range getSubrangeAt( int plcfHddIndex ) { @@ -361,27 +361,27 @@ public final class HeaderStories { headerStories.getStartOffset() + end, headerStories ); } - public Range getRange() { - return headerStories; - } - protected PlexOfCps getPlcfHdd() { - return plcfHdd; - } - - /** - * Are fields currently being stripped from - * the text that this HeaderStories returns? - * Default is false, but can be changed - */ - public boolean areFieldsStripped() { - return stripFields; - } - /** - * Should fields (eg macros) be stripped from - * the text that this class returns? - * Default is not to strip. - */ - public void setAreFieldsStripped(boolean stripFields) { - this.stripFields = stripFields; - } + public Range getRange() { + return headerStories; + } + protected PlexOfCps getPlcfHdd() { + return plcfHdd; + } + + /** + * Are fields currently being stripped from + * the text that this HeaderStories returns? + * Default is false, but can be changed + */ + public boolean areFieldsStripped() { + return stripFields; + } + /** + * Should fields (eg macros) be stripped from + * the text that this class returns? + * Default is not to strip. + */ + public void setAreFieldsStripped(boolean stripFields) { + this.stripFields = stripFields; + } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/Range.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/Range.java index ec37019226..a3fd882d64 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/Range.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/Range.java @@ -56,11 +56,11 @@ public class Range { private static final Logger LOG = LogManager.getLogger(Range.class); - /** + /** * @deprecated POI 3.8 beta 5 */ @Deprecated - public static final int TYPE_PARAGRAPH = 0; + public static final int TYPE_PARAGRAPH = 0; /** * @deprecated POI 3.8 beta 5 @@ -98,226 +98,226 @@ public class Range { @Deprecated public static final int TYPE_UNDEFINED = 6; - /** Needed so inserts and deletes will ripple up through containing Ranges */ - private final Range _parent; - - /** The starting character offset of this range. */ - protected final int _start; - - /** The ending character offset of this range. */ - protected int _end; - - /** The document this range belongs to. */ - protected final HWPFDocumentCore _doc; - - /** Have we loaded the section indexes yet */ - boolean _sectionRangeFound; - - /** All sections that belong to the document this Range belongs to. */ - protected final List<SEPX> _sections; - - /** The start index in the sections list for this Range */ - protected int _sectionStart; - - /** The end index in the sections list for this Range. */ - protected int _sectionEnd; - - /** Have we loaded the paragraph indexes yet. */ - protected boolean _parRangeFound; - - /** All paragraphs that belong to the document this Range belongs to. */ - protected final List<PAPX> _paragraphs; - - /** The start index in the paragraphs list for this Range, inclusive */ - protected int _parStart; - - /** The end index in the paragraphs list for this Range, exclusive */ - protected int _parEnd; - - /** Have we loaded the characterRun indexes yet. */ - protected boolean _charRangeFound; - - /** All CharacterRuns that belong to the document this Range belongs to. */ - protected List<CHPX> _characters; - - /** The start index in the characterRuns list for this Range */ - protected int _charStart; - - /** The end index in the characterRuns list for this Range. */ - protected int _charEnd; - - protected StringBuilder _text; - - /** - * Used to construct a Range from a document. This is generally used to - * create a Range that spans the whole document, or at least one whole part - * of the document (eg main text, header, comment) - * - * @param start Starting character offset of the range. - * @param end Ending character offset of the range. - * @param doc The HWPFDocument the range is based on. - */ - public Range(int start, int end, HWPFDocumentCore doc) { - _start = start; - _end = end; - _doc = doc; - _sections = _doc.getSectionTable().getSections(); - _paragraphs = _doc.getParagraphTable().getParagraphs(); - _characters = _doc.getCharacterTable().getTextRuns(); - _text = _doc.getText(); - _parent = null; - - sanityCheckStartEnd(); - } - - /** - * Used to create Ranges that are children of other Ranges. - * - * @param start Starting character offset of the range. - * @param end Ending character offset of the range. - * @param parent The parent this range belongs to. - */ - protected Range(int start, int end, Range parent) { - _start = start; - _end = end; - _doc = parent._doc; - _sections = parent._sections; - _paragraphs = parent._paragraphs; - _characters = parent._characters; - _text = parent._text; - _parent = parent; - - sanityCheckStartEnd(); - sanityCheck(); - } - - protected Range(Range other) { - _parent = other._parent; - _start = other._start; - _end = other._end; - _doc = other._doc; - _sectionRangeFound = other._sectionRangeFound; - _sections = (other._sections == null) ? null : other._sections.stream().map(SEPX::copy).collect(toList()); - _sectionStart = other._sectionStart; - _sectionEnd = other._sectionEnd; - _parRangeFound = other._parRangeFound; - _paragraphs = (other._paragraphs == null) ? null : other._paragraphs.stream().map(PAPX::copy).collect(toList()); - _parStart = other._parStart; - _parEnd = other._parEnd; - _charRangeFound = other._charRangeFound; - _characters = (other._characters == null) ? null : other._characters.stream().map(CHPX::copy).collect(toList()); - _charStart = other._charStart; - _charEnd = other._charEnd; - _text = (other._text == null) ? null : new StringBuilder(other._text); - } - - - /** - * Ensures that the start and end were were given are actually valid, to - * avoid issues later on if they're not - */ - private void sanityCheckStartEnd() { - if (_start < 0) { - throw new IllegalArgumentException("Range start must not be negative. Given " + _start); - } - if (_end < _start) { - throw new IllegalArgumentException("The end (" + _end - + ") must not be before the start (" + _start + ")"); - } - } - - /** - * Gets the text that this Range contains. - * - * @return The text for this range. - */ - public String text() { - return _text.substring( _start, _end ); - } - - /** - * Removes any fields (eg macros, page markers etc) from the string. - * Normally used to make some text suitable for showing to humans, and the - * resultant text should not normally be saved back into the document! - */ - public static String stripFields(String text) { - // First up, fields can be nested... - // A field can be 0x13 [contents] 0x15 - // Or it can be 0x13 [contents] 0x14 [real text] 0x15 - - // If there are no fields, all easy - if (text.indexOf('\u0013') == -1) - return text; - - // Loop over until they're all gone - // That's when we're out of both 0x13s and 0x15s - while (text.indexOf('\u0013') > -1 && text.indexOf('\u0015') > -1) { - int first13 = text.indexOf('\u0013'); - int next13 = text.indexOf('\u0013', first13 + 1); - int first14 = text.indexOf('\u0014', first13 + 1); - int last15 = text.lastIndexOf('\u0015'); - - // If they're the wrong way around, give up - if (last15 < first13) { - break; - } - - // If no more 13s and 14s, just zap - if (next13 == -1 && first14 == -1) { - text = text.substring(0, first13) + text.substring(last15 + 1); - break; - } - - // If a 14 comes before the next 13, then - // zap from the 13 to the 14, and remove - // the 15 - if (first14 != -1 && (first14 < next13 || next13 == -1)) { - text = text.substring(0, first13) + text.substring(first14 + 1, last15) - + text.substring(last15 + 1); - continue; - } - - // Another 13 comes before the next 14. - // This means there's nested stuff, so we - // can just zap the lot - text = text.substring(0, first13) + text.substring(last15 + 1); - } - - return text; - } - - /** - * Used to get the number of sections in a range. If this range is smaller - * than a section, it will return 1 for its containing section. - * - * @return The number of sections in this range. - */ - public int numSections() { - initSections(); - return _sectionEnd - _sectionStart; - } - - /** - * Used to get the number of paragraphs in a range. If this range is smaller - * than a paragraph, it will return 1 for its containing paragraph. - * - * @return The number of paragraphs in this range. - */ - - public int numParagraphs() { - initParagraphs(); - return _parEnd - _parStart; - } - - /** - * - * @return The number of characterRuns in this range. - */ - - public int numCharacterRuns() { - initCharacterRuns(); - return _charEnd - _charStart; - } + /** Needed so inserts and deletes will ripple up through containing Ranges */ + private final Range _parent; + + /** The starting character offset of this range. */ + protected final int _start; + + /** The ending character offset of this range. */ + protected int _end; + + /** The document this range belongs to. */ + protected final HWPFDocumentCore _doc; + + /** Have we loaded the section indexes yet */ + boolean _sectionRangeFound; + + /** All sections that belong to the document this Range belongs to. */ + protected final List<SEPX> _sections; + + /** The start index in the sections list for this Range */ + protected int _sectionStart; + + /** The end index in the sections list for this Range. */ + protected int _sectionEnd; + + /** Have we loaded the paragraph indexes yet. */ + protected boolean _parRangeFound; + + /** All paragraphs that belong to the document this Range belongs to. */ + protected final List<PAPX> _paragraphs; + + /** The start index in the paragraphs list for this Range, inclusive */ + protected int _parStart; + + /** The end index in the paragraphs list for this Range, exclusive */ + protected int _parEnd; + + /** Have we loaded the characterRun indexes yet. */ + protected boolean _charRangeFound; + + /** All CharacterRuns that belong to the document this Range belongs to. */ + protected List<CHPX> _characters; + + /** The start index in the characterRuns list for this Range */ + protected int _charStart; + + /** The end index in the characterRuns list for this Range. */ + protected int _charEnd; + + protected StringBuilder _text; + + /** + * Used to construct a Range from a document. This is generally used to + * create a Range that spans the whole document, or at least one whole part + * of the document (eg main text, header, comment) + * + * @param start Starting character offset of the range. + * @param end Ending character offset of the range. + * @param doc The HWPFDocument the range is based on. + */ + public Range(int start, int end, HWPFDocumentCore doc) { + _start = start; + _end = end; + _doc = doc; + _sections = _doc.getSectionTable().getSections(); + _paragraphs = _doc.getParagraphTable().getParagraphs(); + _characters = _doc.getCharacterTable().getTextRuns(); + _text = _doc.getText(); + _parent = null; + + sanityCheckStartEnd(); + } + + /** + * Used to create Ranges that are children of other Ranges. + * + * @param start Starting character offset of the range. + * @param end Ending character offset of the range. + * @param parent The parent this range belongs to. + */ + protected Range(int start, int end, Range parent) { + _start = start; + _end = end; + _doc = parent._doc; + _sections = parent._sections; + _paragraphs = parent._paragraphs; + _characters = parent._characters; + _text = parent._text; + _parent = parent; + + sanityCheckStartEnd(); + sanityCheck(); + } + + protected Range(Range other) { + _parent = other._parent; + _start = other._start; + _end = other._end; + _doc = other._doc; + _sectionRangeFound = other._sectionRangeFound; + _sections = (other._sections == null) ? null : other._sections.stream().map(SEPX::copy).collect(toList()); + _sectionStart = other._sectionStart; + _sectionEnd = other._sectionEnd; + _parRangeFound = other._parRangeFound; + _paragraphs = (other._paragraphs == null) ? null : other._paragraphs.stream().map(PAPX::copy).collect(toList()); + _parStart = other._parStart; + _parEnd = other._parEnd; + _charRangeFound = other._charRangeFound; + _characters = (other._characters == null) ? null : other._characters.stream().map(CHPX::copy).collect(toList()); + _charStart = other._charStart; + _charEnd = other._charEnd; + _text = (other._text == null) ? null : new StringBuilder(other._text); + } + + + /** + * Ensures that the start and end were were given are actually valid, to + * avoid issues later on if they're not + */ + private void sanityCheckStartEnd() { + if (_start < 0) { + throw new IllegalArgumentException("Range start must not be negative. Given " + _start); + } + if (_end < _start) { + throw new IllegalArgumentException("The end (" + _end + + ") must not be before the start (" + _start + ")"); + } + } + + /** + * Gets the text that this Range contains. + * + * @return The text for this range. + */ + public String text() { + return _text.substring( _start, _end ); + } + + /** + * Removes any fields (eg macros, page markers etc) from the string. + * Normally used to make some text suitable for showing to humans, and the + * resultant text should not normally be saved back into the document! + */ + public static String stripFields(String text) { + // First up, fields can be nested... + // A field can be 0x13 [contents] 0x15 + // Or it can be 0x13 [contents] 0x14 [real text] 0x15 + + // If there are no fields, all easy + if (text.indexOf('\u0013') == -1) + return text; + + // Loop over until they're all gone + // That's when we're out of both 0x13s and 0x15s + while (text.indexOf('\u0013') > -1 && text.indexOf('\u0015') > -1) { + int first13 = text.indexOf('\u0013'); + int next13 = text.indexOf('\u0013', first13 + 1); + int first14 = text.indexOf('\u0014', first13 + 1); + int last15 = text.lastIndexOf('\u0015'); + + // If they're the wrong way around, give up + if (last15 < first13) { + break; + } + + // If no more 13s and 14s, just zap + if (next13 == -1 && first14 == -1) { + text = text.substring(0, first13) + text.substring(last15 + 1); + break; + } + + // If a 14 comes before the next 13, then + // zap from the 13 to the 14, and remove + // the 15 + if (first14 != -1 && (first14 < next13 || next13 == -1)) { + text = text.substring(0, first13) + text.substring(first14 + 1, last15) + + text.substring(last15 + 1); + continue; + } + + // Another 13 comes before the next 14. + // This means there's nested stuff, so we + // can just zap the lot + text = text.substring(0, first13) + text.substring(last15 + 1); + } + + return text; + } + + /** + * Used to get the number of sections in a range. If this range is smaller + * than a section, it will return 1 for its containing section. + * + * @return The number of sections in this range. + */ + public int numSections() { + initSections(); + return _sectionEnd - _sectionStart; + } + + /** + * Used to get the number of paragraphs in a range. If this range is smaller + * than a paragraph, it will return 1 for its containing paragraph. + * + * @return The number of paragraphs in this range. + */ + + public int numParagraphs() { + initParagraphs(); + return _parEnd - _parStart; + } + + /** + * + * @return The number of characterRuns in this range. + */ + + public int numCharacterRuns() { + initCharacterRuns(); + return _charEnd - _charStart; + } /** * Inserts text into the front of this range. @@ -344,7 +344,7 @@ public class Range { // update the FIB.CCPText + friends fields adjustFIB( text.length() ); - sanityCheck(); + sanityCheck(); return getCharacterRun( 0 ); } @@ -376,195 +376,195 @@ public class Range { return getCharacterRun( numCharacterRuns() - 1 ); } - /** - * Inserts text into the front of this range and it gives that text the - * CharacterProperties specified in props. - * - * @param text - * The text to insert. - * @param props - * The CharacterProperties to give the text. - * @return A new CharacterRun that has the given text and properties and is - * n ow a part of the document. + /** + * Inserts text into the front of this range and it gives that text the + * CharacterProperties specified in props. + * + * @param text + * The text to insert. + * @param props + * The CharacterProperties to give the text. + * @return A new CharacterRun that has the given text and properties and is + * n ow a part of the document. * @deprecated POI 3.8 beta 4. User code should not work with {@link CharacterProperties} - */ + */ @Deprecated - private CharacterRun insertBefore(String text, CharacterProperties props) - { - initAll(); - PAPX papx = _paragraphs.get(_parStart); - short istd = papx.getIstd(); - - StyleSheet ss = _doc.getStyleSheet(); - CharacterProperties baseStyle = ss.getCharacterStyle(istd); - byte[] grpprl = CharacterSprmCompressor.compressCharacterProperty(props, baseStyle); - SprmBuffer buf = new SprmBuffer(grpprl, 0); - _doc.getCharacterTable().insert(_charStart, _start, buf); - - return insertBefore(text); - } - - /** - * Inserts text onto the end of this range and gives that text the - * CharacterProperties specified in props. - * - * @param text - * The text to insert. - * @param props - * The CharacterProperties to give the text. - * @return A new CharacterRun that has the given text and properties and is - * n ow a part of the document. - * @deprecated POI 3.8 beta 4. User code should not work with {@link CharacterProperties} - */ + private CharacterRun insertBefore(String text, CharacterProperties props) + { + initAll(); + PAPX papx = _paragraphs.get(_parStart); + short istd = papx.getIstd(); + + StyleSheet ss = _doc.getStyleSheet(); + CharacterProperties baseStyle = ss.getCharacterStyle(istd); + byte[] grpprl = CharacterSprmCompressor.compressCharacterProperty(props, baseStyle); + SprmBuffer buf = new SprmBuffer(grpprl, 0); + _doc.getCharacterTable().insert(_charStart, _start, buf); + + return insertBefore(text); + } + + /** + * Inserts text onto the end of this range and gives that text the + * CharacterProperties specified in props. + * + * @param text + * The text to insert. + * @param props + * The CharacterProperties to give the text. + * @return A new CharacterRun that has the given text and properties and is + * n ow a part of the document. + * @deprecated POI 3.8 beta 4. User code should not work with {@link CharacterProperties} + */ + @Deprecated + private CharacterRun insertAfter(String text, CharacterProperties props) + { + initAll(); + PAPX papx = _paragraphs.get(_parEnd - 1); + short istd = papx.getIstd(); + + StyleSheet ss = _doc.getStyleSheet(); + CharacterProperties baseStyle = ss.getCharacterStyle(istd); + byte[] grpprl = CharacterSprmCompressor.compressCharacterProperty(props, baseStyle); + SprmBuffer buf = new SprmBuffer(grpprl, 0); + _doc.getCharacterTable().insert(_charEnd, _end, buf); + _charEnd++; + return insertAfter(text); + } + + /** + * Inserts and empty paragraph into the front of this range. + * + * @param props + * The properties that the new paragraph will have. + * @param styleIndex + * The index into the stylesheet for the new paragraph. + * @return The newly inserted paragraph. + * @deprecated POI 3.8 beta 4. Use code shall not work with {@link ParagraphProperties} + */ @Deprecated - private CharacterRun insertAfter(String text, CharacterProperties props) - { - initAll(); - PAPX papx = _paragraphs.get(_parEnd - 1); - short istd = papx.getIstd(); - - StyleSheet ss = _doc.getStyleSheet(); - CharacterProperties baseStyle = ss.getCharacterStyle(istd); - byte[] grpprl = CharacterSprmCompressor.compressCharacterProperty(props, baseStyle); - SprmBuffer buf = new SprmBuffer(grpprl, 0); - _doc.getCharacterTable().insert(_charEnd, _end, buf); - _charEnd++; - return insertAfter(text); - } - - /** - * Inserts and empty paragraph into the front of this range. - * - * @param props - * The properties that the new paragraph will have. - * @param styleIndex - * The index into the stylesheet for the new paragraph. - * @return The newly inserted paragraph. - * @deprecated POI 3.8 beta 4. Use code shall not work with {@link ParagraphProperties} - */ - @Deprecated - private Paragraph insertBefore(ParagraphProperties props, int styleIndex) - { - return this.insertBefore(props, styleIndex, "\r"); - } - - /** - * Inserts a paragraph into the front of this range. The paragraph will - * contain one character run that has the default properties for the - * paragraph's style. - * - * It is necessary for the text to end with the character '\r' - * - * @param props - * The paragraph's properties. - * @param styleIndex - * The index of the paragraph's style in the style sheet. - * @param text - * The text to insert. - * @return A newly inserted paragraph. + private Paragraph insertBefore(ParagraphProperties props, int styleIndex) + { + return this.insertBefore(props, styleIndex, "\r"); + } + + /** + * Inserts a paragraph into the front of this range. The paragraph will + * contain one character run that has the default properties for the + * paragraph's style. + * + * It is necessary for the text to end with the character '\r' + * + * @param props + * The paragraph's properties. + * @param styleIndex + * The index of the paragraph's style in the style sheet. + * @param text + * The text to insert. + * @return A newly inserted paragraph. * @deprecated POI 3.8 beta 4. Use code shall not work with {@link ParagraphProperties} - */ + */ @Deprecated - private Paragraph insertBefore(ParagraphProperties props, int styleIndex, String text) - { - initAll(); - StyleSheet ss = _doc.getStyleSheet(); - ParagraphProperties baseStyle = ss.getParagraphStyle(styleIndex); - CharacterProperties baseChp = ss.getCharacterStyle(styleIndex); - - byte[] grpprl = ParagraphSprmCompressor.compressParagraphProperty(props, baseStyle); - byte[] withIndex = new byte[grpprl.length + LittleEndianConsts.SHORT_SIZE]; - LittleEndian.putShort(withIndex, 0, (short) styleIndex); - System.arraycopy(grpprl, 0, withIndex, LittleEndianConsts.SHORT_SIZE, grpprl.length); - SprmBuffer buf = new SprmBuffer(withIndex, 2); - - _doc.getParagraphTable().insert(_parStart, _start, buf); - insertBefore(text, baseChp); - return getParagraph(0); - } - - /** - * Inserts and empty paragraph into the end of this range. - * - * @param props - * The properties that the new paragraph will have. - * @param styleIndex - * The index into the stylesheet for the new paragraph. - * @return The newly inserted paragraph. + private Paragraph insertBefore(ParagraphProperties props, int styleIndex, String text) + { + initAll(); + StyleSheet ss = _doc.getStyleSheet(); + ParagraphProperties baseStyle = ss.getParagraphStyle(styleIndex); + CharacterProperties baseChp = ss.getCharacterStyle(styleIndex); + + byte[] grpprl = ParagraphSprmCompressor.compressParagraphProperty(props, baseStyle); + byte[] withIndex = new byte[grpprl.length + LittleEndianConsts.SHORT_SIZE]; + LittleEndian.putShort(withIndex, 0, (short) styleIndex); + System.arraycopy(grpprl, 0, withIndex, LittleEndianConsts.SHORT_SIZE, grpprl.length); + SprmBuffer buf = new SprmBuffer(withIndex, 2); + + _doc.getParagraphTable().insert(_parStart, _start, buf); + insertBefore(text, baseChp); + return getParagraph(0); + } + + /** + * Inserts and empty paragraph into the end of this range. + * + * @param props + * The properties that the new paragraph will have. + * @param styleIndex + * The index into the stylesheet for the new paragraph. + * @return The newly inserted paragraph. * @deprecated POI 3.8 beta 4. Use code shall not work with {@link ParagraphProperties} - */ + */ @Deprecated - Paragraph insertAfter(ParagraphProperties props, int styleIndex) - { - return this.insertAfter(props, styleIndex, "\r"); - } - - /** - * Inserts a paragraph into the end of this range. The paragraph will - * contain one character run that has the default properties for the - * paragraph's style. - * - * It is necessary for the text to end with the character '\r' - * - * @param props - * The paragraph's properties. - * @param styleIndex - * The index of the paragraph's style in the style sheet. - * @param text - * The text to insert. - * @return A newly inserted paragraph. + Paragraph insertAfter(ParagraphProperties props, int styleIndex) + { + return this.insertAfter(props, styleIndex, "\r"); + } + + /** + * Inserts a paragraph into the end of this range. The paragraph will + * contain one character run that has the default properties for the + * paragraph's style. + * + * It is necessary for the text to end with the character '\r' + * + * @param props + * The paragraph's properties. + * @param styleIndex + * The index of the paragraph's style in the style sheet. + * @param text + * The text to insert. + * @return A newly inserted paragraph. * @deprecated POI 3.8 beta 4. Use code shall not work with {@link ParagraphProperties} - */ + */ @Deprecated - Paragraph insertAfter(ParagraphProperties props, int styleIndex, String text) - { - initAll(); - StyleSheet ss = _doc.getStyleSheet(); - ParagraphProperties baseStyle = ss.getParagraphStyle(styleIndex); - CharacterProperties baseChp = ss.getCharacterStyle(styleIndex); - - byte[] grpprl = ParagraphSprmCompressor.compressParagraphProperty(props, baseStyle); - byte[] withIndex = new byte[grpprl.length + LittleEndianConsts.SHORT_SIZE]; - LittleEndian.putShort(withIndex, 0, (short) styleIndex); - System.arraycopy(grpprl, 0, withIndex, LittleEndianConsts.SHORT_SIZE, grpprl.length); - SprmBuffer buf = new SprmBuffer(withIndex, 2); - - _doc.getParagraphTable().insert(_parEnd, _end, buf); - _parEnd++; - insertAfter(text, baseChp); - return getParagraph(numParagraphs() - 1); - } - - public void delete() { - - initAll(); - - int numSections = _sections.size(); - int numRuns = _characters.size(); - int numParagraphs = _paragraphs.size(); - - for (int x = _charStart; x < numRuns; x++) { - CHPX chpx = _characters.get(x); - chpx.adjustForDelete(_start, _end - _start); - } - - for (int x = _parStart; x < numParagraphs; x++) { - PAPX papx = _paragraphs.get(x); - // System.err.println("Paragraph " + x + " was " + papx.getStart() + - // " -> " + papx.getEnd()); - papx.adjustForDelete(_start, _end - _start); - // System.err.println("Paragraph " + x + " is now " + - // papx.getStart() + " -> " + papx.getEnd()); - } - - for (int x = _sectionStart; x < numSections; x++) { - SEPX sepx = _sections.get(x); - // System.err.println("Section " + x + " was " + sepx.getStart() + - // " -> " + sepx.getEnd()); - sepx.adjustForDelete(_start, _end - _start); - // System.err.println("Section " + x + " is now " + sepx.getStart() - // + " -> " + sepx.getEnd()); - } + Paragraph insertAfter(ParagraphProperties props, int styleIndex, String text) + { + initAll(); + StyleSheet ss = _doc.getStyleSheet(); + ParagraphProperties baseStyle = ss.getParagraphStyle(styleIndex); + CharacterProperties baseChp = ss.getCharacterStyle(styleIndex); + + byte[] grpprl = ParagraphSprmCompressor.compressParagraphProperty(props, baseStyle); + byte[] withIndex = new byte[grpprl.length + LittleEndianConsts.SHORT_SIZE]; + LittleEndian.putShort(withIndex, 0, (short) styleIndex); + System.arraycopy(grpprl, 0, withIndex, LittleEndianConsts.SHORT_SIZE, grpprl.length); + SprmBuffer buf = new SprmBuffer(withIndex, 2); + + _doc.getParagraphTable().insert(_parEnd, _end, buf); + _parEnd++; + insertAfter(text, baseChp); + return getParagraph(numParagraphs() - 1); + } + + public void delete() { + + initAll(); + + int numSections = _sections.size(); + int numRuns = _characters.size(); + int numParagraphs = _paragraphs.size(); + + for (int x = _charStart; x < numRuns; x++) { + CHPX chpx = _characters.get(x); + chpx.adjustForDelete(_start, _end - _start); + } + + for (int x = _parStart; x < numParagraphs; x++) { + PAPX papx = _paragraphs.get(x); + // System.err.println("Paragraph " + x + " was " + papx.getStart() + + // " -> " + papx.getEnd()); + papx.adjustForDelete(_start, _end - _start); + // System.err.println("Paragraph " + x + " is now " + + // papx.getStart() + " -> " + papx.getEnd()); + } + + for (int x = _sectionStart; x < numSections; x++) { + SEPX sepx = _sections.get(x); + // System.err.println("Section " + x + " was " + sepx.getStart() + + // " -> " + sepx.getEnd()); + sepx.adjustForDelete(_start, _end - _start); + // System.err.println("Section " + x + " is now " + sepx.getStart() + // + " -> " + sepx.getEnd()); + } if ( _doc instanceof HWPFDocument ) { @@ -579,9 +579,9 @@ public class Range { parent.adjustForInsert( -( _end - _start ) ); } - // update the FIB.CCPText + friends field - adjustFIB(-(_end - _start)); - } + // update the FIB.CCPText + friends field + adjustFIB(-(_end - _start)); + } /** * Inserts a simple table into the beginning of this range. @@ -592,7 +592,7 @@ public class Range { * The number of rows. * @return The empty Table that is now part of the document. */ - public Table insertTableBefore(short columns, int rows) { + public Table insertTableBefore(short columns, int rows) { ParagraphProperties parProps = new ParagraphProperties(); parProps.setFInTable(true); parProps.setItap( 1 ); @@ -617,7 +617,7 @@ public class Range { final int diff = newEnd - oldEnd; return new Table( _start, _start + diff, this, 1 ); - } + } /** * Replace range text with new one, adding it to the range and deleting @@ -648,60 +648,60 @@ public class Range { } } - /** - * Replace (one instance of) a piece of text with another... - * - * @param pPlaceHolder - * The text to be replaced (e.g., "${organization}") - * @param pValue - * The replacement text (e.g., "Apache Software Foundation") - * @param pOffset - * The offset or index where the text to be replaced begins - * (relative to/within this {@code Range}) - */ - @Internal - public void replaceText(String pPlaceHolder, String pValue, int pOffset) { - int absPlaceHolderIndex = getStartOffset() + pOffset; - - Range subRange = new Range(absPlaceHolderIndex, - (absPlaceHolderIndex + pPlaceHolder.length()), this); - subRange.insertBefore(pValue); - - // re-create the sub-range so we can delete it - subRange = new Range((absPlaceHolderIndex + pValue.length()), (absPlaceHolderIndex - + pPlaceHolder.length() + pValue.length()), this); - - // deletes are automagically propagated - subRange.delete(); - } - - /** - * Replace (all instances of) a piece of text with another... - * - * @param pPlaceHolder - * The text to be replaced (e.g., "${organization}") - * @param pValue - * The replacement text (e.g., "Apache Software Foundation") - */ - public void replaceText(String pPlaceHolder, String pValue) { - while (true) { - String text = text(); - int offset = text.indexOf(pPlaceHolder); - if (offset >= 0) { - replaceText(pPlaceHolder, pValue, offset); - } else { - break; - } - } - } - - /** - * Gets the character run at index. The index is relative to this range. - * - * @param index - * The index of the character run to get. - * @return The character run at the specified index in this range. - */ + /** + * Replace (one instance of) a piece of text with another... + * + * @param pPlaceHolder + * The text to be replaced (e.g., "${organization}") + * @param pValue + * The replacement text (e.g., "Apache Software Foundation") + * @param pOffset + * The offset or index where the text to be replaced begins + * (relative to/within this {@code Range}) + */ + @Internal + public void replaceText(String pPlaceHolder, String pValue, int pOffset) { + int absPlaceHolderIndex = getStartOffset() + pOffset; + + Range subRange = new Range(absPlaceHolderIndex, + (absPlaceHolderIndex + pPlaceHolder.length()), this); + subRange.insertBefore(pValue); + + // re-create the sub-range so we can delete it + subRange = new Range((absPlaceHolderIndex + pValue.length()), (absPlaceHolderIndex + + pPlaceHolder.length() + pValue.length()), this); + + // deletes are automagically propagated + subRange.delete(); + } + + /** + * Replace (all instances of) a piece of text with another... + * + * @param pPlaceHolder + * The text to be replaced (e.g., "${organization}") + * @param pValue + * The replacement text (e.g., "Apache Software Foundation") + */ + public void replaceText(String pPlaceHolder, String pValue) { + while (true) { + String text = text(); + int offset = text.indexOf(pPlaceHolder); + if (offset >= 0) { + replaceText(pPlaceHolder, pValue, offset); + } else { + break; + } + } + } + + /** + * Gets the character run at index. The index is relative to this range. + * + * @param index + * The index of the character run to get. + * @return The character run at the specified index in this range. + */ public CharacterRun getCharacterRun( int index ) { initCharacterRuns(); @@ -740,32 +740,32 @@ public class Range { istd = papx.getIstd(); } - return new CharacterRun( chpx, _doc.getStyleSheet(), istd, - this); + return new CharacterRun( chpx, _doc.getStyleSheet(), istd, + this); } - /** - * Gets the section at index. The index is relative to this range. - * - * @param index - * The index of the section to get. - * @return The section at the specified index in this range. - */ - public Section getSection(int index) { - initSections(); - SEPX sepx = _sections.get(index + _sectionStart); - return new Section(sepx, this); - } - - /** - * Gets the paragraph at index. The index is relative to this range. - * - * @param index - * The index of the paragraph to get. - * @return The paragraph at the specified index in this range. - */ - - public Paragraph getParagraph(int index) { + /** + * Gets the section at index. The index is relative to this range. + * + * @param index + * The index of the section to get. + * @return The section at the specified index in this range. + */ + public Section getSection(int index) { + initSections(); + SEPX sepx = _sections.get(index + _sectionStart); + return new Section(sepx, this); + } + + /** + * Gets the paragraph at index. The index is relative to this range. + * + * @param index + * The index of the paragraph to get. + * @return The paragraph at the specified index in this range. + */ + + public Paragraph getParagraph(int index) { initParagraphs(); if ( index + _parStart >= _parEnd ) @@ -773,27 +773,27 @@ public class Range { + (index + _parStart) + ") not in range [" + _parStart + "; " + _parEnd + ")" ); - PAPX papx = _paragraphs.get(index + _parStart); - return Paragraph.newParagraph( this, papx ); - } - - /** - * Gets the table that starts with paragraph. In a Word file, a table - * consists of a group of paragraphs with certain flags set. - * - * @param paragraph - * The paragraph that is the first paragraph in the table. - * @return The table that starts with paragraph - */ - public Table getTable(Paragraph paragraph) { - if (!paragraph.isInTable()) { - throw new IllegalArgumentException("This paragraph doesn't belong to a table"); - } - - Range r = paragraph; - if (r._parent != this) { - throw new IllegalArgumentException("This paragraph is not a child of this range instance"); - } + PAPX papx = _paragraphs.get(index + _parStart); + return Paragraph.newParagraph( this, papx ); + } + + /** + * Gets the table that starts with paragraph. In a Word file, a table + * consists of a group of paragraphs with certain flags set. + * + * @param paragraph + * The paragraph that is the first paragraph in the table. + * @return The table that starts with paragraph + */ + public Table getTable(Paragraph paragraph) { + if (!paragraph.isInTable()) { + throw new IllegalArgumentException("This paragraph doesn't belong to a table"); + } + + Range r = paragraph; + if (r._parent != this) { + throw new IllegalArgumentException("This paragraph is not a child of this range instance"); + } r.initAll(); int tableLevel = paragraph.getTableLevel(); @@ -825,8 +825,8 @@ public class Range { initAll(); if ( tableEndInclusive >= this._parEnd ) { - LOG.atWarn().log("The table's bounds [{}; {}) fall outside of this Range paragraphs numbers [{}; {})", - this._parStart, box(tableEndInclusive),box(this._parStart),box(this._parEnd)); + LOG.atWarn().log("The table's bounds [{}; {}) fall outside of this Range paragraphs numbers [{}; {})", + this._parStart, box(tableEndInclusive),box(this._parStart),box(this._parEnd)); } if ( tableEndInclusive < 0 ) @@ -841,50 +841,50 @@ public class Range { this, paragraph.getTableLevel() ); } - /** - * loads all of the list indexes. - */ - protected void initAll() { - initCharacterRuns(); - initParagraphs(); - initSections(); - } - - /** - * inits the paragraph list indexes. - */ - private void initParagraphs() { - if (!_parRangeFound) { - int[] point = findRange(_paragraphs, _start, _end); - _parStart = point[0]; - _parEnd = point[1]; - _parRangeFound = true; - } - } - - /** - * inits the character run list indexes. - */ - private void initCharacterRuns() { - if (!_charRangeFound) { - int[] point = findRange(_characters, _start, _end); - _charStart = point[0]; - _charEnd = point[1]; - _charRangeFound = true; - } - } - - /** - * inits the section list indexes. - */ - private void initSections() { - if (!_sectionRangeFound) { - int[] point = findRange(_sections, _sectionStart, _start, _end); - _sectionStart = point[0]; - _sectionEnd = point[1]; - _sectionRangeFound = true; - } - } + /** + * loads all of the list indexes. + */ + protected void initAll() { + initCharacterRuns(); + initParagraphs(); + initSections(); + } + + /** + * inits the paragraph list indexes. + */ + private void initParagraphs() { + if (!_parRangeFound) { + int[] point = findRange(_paragraphs, _start, _end); + _parStart = point[0]; + _parEnd = point[1]; + _parRangeFound = true; + } + } + + /** + * inits the character run list indexes. + */ + private void initCharacterRuns() { + if (!_charRangeFound) { + int[] point = findRange(_characters, _start, _end); + _charStart = point[0]; + _charEnd = point[1]; + _charRangeFound = true; + } + } + + /** + * inits the section list indexes. + */ + private void initSections() { + if (!_sectionRangeFound) { + int[] point = findRange(_sections, _sectionStart, _start, _end); + _sectionStart = point[0]; + _sectionEnd = point[1]; + _sectionRangeFound = true; + } + } private static int binarySearchStart( List<? extends PropertyNode<?>> rpl, int start ) @@ -980,43 +980,43 @@ public class Range { if ( startIndex < 0 || startIndex >= rpl.size() || startIndex > endIndex || endIndex < 0 || endIndex >= rpl.size() ) { - throw new DocumentFormatException("problem finding range"); - } + throw new DocumentFormatException("problem finding range"); + } return new int[] { startIndex, endIndex + 1 }; } - /** - * Used to find the list indexes of a particular property. - * - * @param rpl - * A list of property nodes. - * @param min - * A hint on where to start looking. - * @param start - * The starting character offset. - * @param end - * The ending character offset. - * @return An int array of length 2. The first int is the start index and - * the second int is the end index. - */ - private int[] findRange(List<? extends PropertyNode<?>> rpl, int min, int start, int end) { - int x = min; + /** + * Used to find the list indexes of a particular property. + * + * @param rpl + * A list of property nodes. + * @param min + * A hint on where to start looking. + * @param start + * The starting character offset. + * @param end + * The ending character offset. + * @return An int array of length 2. The first int is the start index and + * the second int is the end index. + */ + private int[] findRange(List<? extends PropertyNode<?>> rpl, int min, int start, int end) { + int x = min; if ( rpl.size() == min ) return new int[] { min, min }; PropertyNode<?> node = rpl.get( x ); - while (node==null || (node.getEnd() <= start && x < rpl.size() - 1)) { - x++; + while (node==null || (node.getEnd() <= start && x < rpl.size() - 1)) { + x++; if (x>=rpl.size()) { return new int[] {0, 0}; } - node = rpl.get(x); - } + node = rpl.get(x); + } if ( node.getStart() > end ) { @@ -1045,14 +1045,14 @@ public class Range { return new int[] { x, rpl.size() }; } - /** - * resets the list indexes. - */ - protected void reset() { - _charRangeFound = false; - _parRangeFound = false; - _sectionRangeFound = false; - } + /** + * resets the list indexes. + */ + protected void reset() { + _charRangeFound = false; + _parRangeFound = false; + _sectionRangeFound = false; + } /** * Adjust the value of the various FIB character count fields, eg @@ -1066,8 +1066,8 @@ public class Range { protected void adjustFIB( int adjustment ) { if (!( _doc instanceof HWPFDocument)) { - throw new IllegalArgumentException("doc must be instance of HWPFDocument"); - } + throw new IllegalArgumentException("doc must be instance of HWPFDocument"); + } // update the FIB.CCPText field (this should happen once per adjustment, // so we don't want it in @@ -1121,40 +1121,40 @@ public class Range { } } - /** - * adjust this range after an insert happens. - * - * @param length - * the length to adjust for (expected to be a count of - * code-points, not necessarily chars) - */ - private void adjustForInsert(int length) { - _end += length; - - reset(); - Range parent = _parent; - if (parent != null) { - parent.adjustForInsert(length); - } - } - - /** - * @return Starting character offset of the range - */ - public int getStartOffset() { - return _start; - } - - /** - * @return The ending character offset of this range - */ - public int getEndOffset() { - return _end; - } - - protected HWPFDocumentCore getDocument() { - return _doc; - } + /** + * adjust this range after an insert happens. + * + * @param length + * the length to adjust for (expected to be a count of + * code-points, not necessarily chars) + */ + private void adjustForInsert(int length) { + _end += length; + + reset(); + Range parent = _parent; + if (parent != null) { + parent.adjustForInsert(length); + } + } + + /** + * @return Starting character offset of the range + */ + public int getStartOffset() { + return _start; + } + + /** + * @return The ending character offset of this range + */ + public int getEndOffset() { + return _end; + } + + protected HWPFDocumentCore getDocument() { + return _doc; + } @Override public String toString() @@ -1169,14 +1169,14 @@ public class Range { */ public boolean sanityCheck() { - DocumentFormatException.check(_start >= 0, - "start can't be < 0"); - DocumentFormatException.check( _start <= _text.length(), - "start can't be > text length"); + DocumentFormatException.check(_start >= 0, + "start can't be < 0"); + DocumentFormatException.check( _start <= _text.length(), + "start can't be > text length"); DocumentFormatException.check( _end >= 0, - "end can't be < 0"); + "end can't be < 0"); DocumentFormatException.check( _end <= _text.length(), - "end can't be > text length"); + "end can't be > text length"); DocumentFormatException.check( _start <= _end,"start can't be > end"); if ( _charRangeFound ) @@ -1200,7 +1200,7 @@ public class Range { int right = Math.min( this._end, papx.getEnd() ); DocumentFormatException.check( left < right, - "left must be < right"); + "left must be < right"); } } return true; diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/TestHDGFLZW.java b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/TestHDGFLZW.java index 86163afe33..674156c00a 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/TestHDGFLZW.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/TestHDGFLZW.java @@ -125,11 +125,11 @@ public final class TestHDGFLZW { assertEquals(632, dec.length); /* - // Encode it again using our engine - byte[] comp = lzw.compress(new ByteArrayInputStream(testTrailerDecomp)); + // Encode it again using our engine + byte[] comp = lzw.compress(new ByteArrayInputStream(testTrailerDecomp)); - // Check it's of the right size - assertEquals(339, comp.length); + // Check it's of the right size + assertEquals(339, comp.length); */ } @@ -164,12 +164,12 @@ public final class TestHDGFLZW { byte[] decomp = lzw.decompress(new ByteArrayInputStream(comp)); // First up, check the round tripping - assertEquals(12, decomp.length); - assertArrayEquals(Arrays.copyOfRange(testTrailerDecomp, 0, decomp.length), decomp); + assertEquals(12, decomp.length); + assertArrayEquals(Arrays.copyOfRange(testTrailerDecomp, 0, decomp.length), decomp); // Now check the compressed intermediate version assertEquals(11, comp.length); - assertArrayEquals(Arrays.copyOfRange(testTrailerComp, 0, comp.length), comp); + assertArrayEquals(Arrays.copyOfRange(testTrailerComp, 0, comp.length), comp); } /** @@ -192,7 +192,7 @@ public final class TestHDGFLZW { // We can only check the round-tripping, as for now // visio cheats on re-using a block - assertArrayEquals(sourceDecomp, decomp); + assertArrayEquals(sourceDecomp, decomp); } @Test diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/chunks/TestChunks.java b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/chunks/TestChunks.java index 3b97b03b50..58254a5933 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/chunks/TestChunks.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/chunks/TestChunks.java @@ -30,160 +30,160 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; public final class TestChunks { - private static byte[] data_a, data_b; - - @BeforeAll - public static void setup() throws IOException { - data_a = RawDataUtil.decompress( - "H4sIAAAAAAAAAHNjYGD4DwRMQNqFAQygFAMTWAIbYIBqQqZRARMSOwNKMwOxChAzMoRIACkeNC3MUAwDjEjGTEISb" + - "wGLh3pCeCfsoYwD9vbojP1QqQ/2cAYLplNBIACV+8EeuzKE2/4DXaoAZm6HOhUE/CFOU1BwgCnEw+DgcIQxHXGrYv" + - "zMD6JOMCACwwNiC9SNF+zxMFC988GeEepUdrg/+MHMVKgnQFiGAR5F6KEFU4IMmpHYXBCXsUIdCQUApUvwomMCAAA="); - data_b = RawDataUtil.decompress( - "H4sIAAAAAAAAAHNjYGD4DwTMQNqFAQygFAMTWAIbYIBqQqZRATMSOwNuHgODAhAzMoRIACkONC1MUAwDjFB6EpJYC" + - "1hNqD2Ep+gAZajBGAfsYYz9nhDGB3s4A9OVYBCAysWpDu4uYFixKICZJ5Cc6YHitAv2eBioFn2wZwQZwsjIwA63gR" + - "/MTIUaD8IyDPCAY0F3EJIrYKAZic0FcRkrkPKDC55kQIR2G9iAAJAZNlDMii8EaAoA66WHVpECAAA="); - } + private static byte[] data_a, data_b; + + @BeforeAll + public static void setup() throws IOException { + data_a = RawDataUtil.decompress( + "H4sIAAAAAAAAAHNjYGD4DwRMQNqFAQygFAMTWAIbYIBqQqZRARMSOwNKMwOxChAzMoRIACkeNC3MUAwDjEjGTEISb" + + "wGLh3pCeCfsoYwD9vbojP1QqQ/2cAYLplNBIACV+8EeuzKE2/4DXaoAZm6HOhUE/CFOU1BwgCnEw+DgcIQxHXGrYv" + + "zMD6JOMCACwwNiC9SNF+zxMFC988GeEepUdrg/+MHMVKgnQFiGAR5F6KEFU4IMmpHYXBCXsUIdCQUApUvwomMCAAA="); + data_b = RawDataUtil.decompress( + "H4sIAAAAAAAAAHNjYGD4DwTMQNqFAQygFAMTWAIbYIBqQqZRATMSOwNuHgODAhAzMoRIACkONC1MUAwDjFB6EpJYC" + + "1hNqD2Ep+gAZajBGAfsYYz9nhDGB3s4A9OVYBCAysWpDu4uYFixKICZJ5Cc6YHitAv2eBioFn2wZwQZwsjIwA63gR" + + "/MTIUaD8IyDPCAY0F3EJIrYKAZic0FcRkrkPKDC55kQIR2G9iAAJAZNlDMii8EaAoA66WHVpECAAA="); + } @Test - void testChunkHeaderA() { - ChunkHeader h = ChunkHeader.createChunkHeader(11, data_a, 0); + void testChunkHeaderA() { + ChunkHeader h = ChunkHeader.createChunkHeader(11, data_a, 0); - assertTrue(h instanceof ChunkHeaderV11); - ChunkHeaderV11 header = (ChunkHeaderV11)h; + assertTrue(h instanceof ChunkHeaderV11); + ChunkHeaderV11 header = (ChunkHeaderV11)h; - assertEquals(70, header.getType()); - assertEquals(-1, header.getId()); - assertEquals(2, header.getUnknown1()); - assertEquals(68, header.getLength()); - assertEquals(0, header.getUnknown2()); - assertEquals(0, header.getUnknown3()); + assertEquals(70, header.getType()); + assertEquals(-1, header.getId()); + assertEquals(2, header.getUnknown1()); + assertEquals(68, header.getLength()); + assertEquals(0, header.getUnknown2()); + assertEquals(0, header.getUnknown3()); - assertTrue(header.hasTrailer()); - assertTrue(header.hasSeparator()); - } + assertTrue(header.hasTrailer()); + assertTrue(header.hasSeparator()); + } @Test void testChunkHeaderB() { - ChunkHeader h = ChunkHeader.createChunkHeader(11, data_b, 0); + ChunkHeader h = ChunkHeader.createChunkHeader(11, data_b, 0); - assertTrue(h instanceof ChunkHeaderV11); - ChunkHeaderV11 header = (ChunkHeaderV11)h; + assertTrue(h instanceof ChunkHeaderV11); + ChunkHeaderV11 header = (ChunkHeaderV11)h; - assertEquals(70, header.getType()); - assertEquals(-1, header.getId()); - assertEquals(3, header.getUnknown1()); - assertEquals(68, header.getLength()); - assertEquals(0, header.getUnknown2()); - assertEquals(0, header.getUnknown3()); + assertEquals(70, header.getType()); + assertEquals(-1, header.getId()); + assertEquals(3, header.getUnknown1()); + assertEquals(68, header.getLength()); + assertEquals(0, header.getUnknown2()); + assertEquals(0, header.getUnknown3()); - assertTrue(header.hasTrailer()); - assertTrue(header.hasSeparator()); - } + assertTrue(header.hasTrailer()); + assertTrue(header.hasSeparator()); + } @Test void testOneChunk() throws Exception { - ChunkFactory cf = new ChunkFactory(11); - cf.createChunk(data_a, 0); - cf.createChunk(data_b, 0); + ChunkFactory cf = new ChunkFactory(11); + cf.createChunk(data_a, 0); + cf.createChunk(data_b, 0); - Chunk chunk = cf.createChunk(data_a, 0); - assertNotNull(chunk.getHeader()); - assertNotNull(chunk.getTrailer()); - assertNotNull(chunk.getSeparator()); + Chunk chunk = cf.createChunk(data_a, 0); + assertNotNull(chunk.getHeader()); + assertNotNull(chunk.getTrailer()); + assertNotNull(chunk.getSeparator()); - // Should be 19 + length + 8 + 4 big - assertEquals(68, chunk.getHeader().getLength()); - assertEquals(68+19+8+4, chunk.getOnDiskSize()); + // Should be 19 + length + 8 + 4 big + assertEquals(68, chunk.getHeader().getLength()); + assertEquals(68+19+8+4, chunk.getOnDiskSize()); - // Type is 70, or 0x46 - assertEquals(70, chunk.getHeader().getType()); - assertEquals(0x46, chunk.getHeader().getType()); + // Type is 70, or 0x46 + assertEquals(70, chunk.getHeader().getType()); + assertEquals(0x46, chunk.getHeader().getType()); - // Should have two virtual chunk commands, a - // 10 (page sheet) and an 18 - assertEquals(2, chunk.getCommandDefinitions().length); - assertEquals(0, chunk.getCommands().length); + // Should have two virtual chunk commands, a + // 10 (page sheet) and an 18 + assertEquals(2, chunk.getCommandDefinitions().length); + assertEquals(0, chunk.getCommands().length); - assertEquals(10, chunk.getCommandDefinitions()[0].getType()); - assertEquals(0, chunk.getCommandDefinitions()[0].getOffset()); - assertEquals("PageSheet", chunk.getCommandDefinitions()[0].getName()); + assertEquals(10, chunk.getCommandDefinitions()[0].getType()); + assertEquals(0, chunk.getCommandDefinitions()[0].getOffset()); + assertEquals("PageSheet", chunk.getCommandDefinitions()[0].getName()); - assertEquals(18, chunk.getCommandDefinitions()[1].getType()); - assertEquals(0, chunk.getCommandDefinitions()[1].getOffset()); - assertEquals("0", chunk.getCommandDefinitions()[1].getName()); - } + assertEquals(18, chunk.getCommandDefinitions()[1].getType()); + assertEquals(0, chunk.getCommandDefinitions()[1].getOffset()); + assertEquals("0", chunk.getCommandDefinitions()[1].getName()); + } @Test void testAnotherChunk() throws Exception { - ChunkFactory cf = new ChunkFactory(11); + ChunkFactory cf = new ChunkFactory(11); - // Go for the 2nd chunk in the stream - int offset = 0; - Chunk chunk = cf.createChunk(data_b, offset); - offset += chunk.getOnDiskSize(); - chunk = cf.createChunk(data_b, offset); + // Go for the 2nd chunk in the stream + int offset = 0; + Chunk chunk = cf.createChunk(data_b, offset); + offset += chunk.getOnDiskSize(); + chunk = cf.createChunk(data_b, offset); - assertNotNull(chunk.getHeader()); - assertNotNull(chunk.getTrailer()); - assertNotNull(chunk.getSeparator()); + assertNotNull(chunk.getHeader()); + assertNotNull(chunk.getTrailer()); + assertNotNull(chunk.getSeparator()); - // Should be 19 + length + 8 + 4 big - assertEquals(32, chunk.getHeader().getLength()); - assertEquals(32+19+8+4, chunk.getOnDiskSize()); + // Should be 19 + length + 8 + 4 big + assertEquals(32, chunk.getHeader().getLength()); + assertEquals(32+19+8+4, chunk.getOnDiskSize()); - // Type is 104, or 0x68 - assertEquals(104, chunk.getHeader().getType()); - assertEquals(0x68, chunk.getHeader().getType()); + // Type is 104, or 0x68 + assertEquals(104, chunk.getHeader().getType()); + assertEquals(0x68, chunk.getHeader().getType()); - // Should have two virtual chunk commands, a - // 10 (Unknown) and an 18 - final CommandDefinition[] cdef = chunk.getCommandDefinitions(); - assertEquals(2, cdef.length); - assertEquals(0, chunk.getCommands().length); + // Should have two virtual chunk commands, a + // 10 (Unknown) and an 18 + final CommandDefinition[] cdef = chunk.getCommandDefinitions(); + assertEquals(2, cdef.length); + assertEquals(0, chunk.getCommands().length); - assertEquals(10, cdef[0].getType()); - assertEquals(0, cdef[0].getOffset()); - assertEquals("PropList", cdef[0].getName()); + assertEquals(10, cdef[0].getType()); + assertEquals(0, cdef[0].getOffset()); + assertEquals("PropList", cdef[0].getName()); - assertEquals(18, cdef[1].getType()); - assertEquals(0, cdef[1].getOffset()); - assertEquals("0", cdef[1].getName()); - } + assertEquals(18, cdef[1].getType()); + assertEquals(0, cdef[1].getOffset()); + assertEquals("0", cdef[1].getName()); + } @Test void testManyChunks() throws Exception { - ChunkFactory cf = new ChunkFactory(11); - Chunk chunk; - int offset = 0; - - chunk = cf.createChunk(data_a, offset); - assertNotNull(chunk.getHeader()); - assertNotNull(chunk.getTrailer()); - assertNotNull(chunk.getSeparator()); - offset += chunk.getOnDiskSize(); - - chunk = cf.createChunk(data_a, offset); - assertNotNull(chunk.getHeader()); - assertNotNull(chunk.getTrailer()); - assertNotNull(chunk.getSeparator()); - offset += chunk.getOnDiskSize(); - - // Has a separator but no trailer - chunk = cf.createChunk(data_a, offset); - assertNotNull(chunk.getHeader()); - assertNull(chunk.getTrailer()); - assertNotNull(chunk.getSeparator()); - offset += chunk.getOnDiskSize(); - - chunk = cf.createChunk(data_a, offset); - assertNotNull(chunk.getHeader()); - assertNull(chunk.getTrailer()); - assertNotNull(chunk.getSeparator()); - offset += chunk.getOnDiskSize(); - - chunk = cf.createChunk(data_a, offset); - assertNotNull(chunk.getHeader()); - assertNull(chunk.getTrailer()); - assertNotNull(chunk.getSeparator()); - } + ChunkFactory cf = new ChunkFactory(11); + Chunk chunk; + int offset = 0; + + chunk = cf.createChunk(data_a, offset); + assertNotNull(chunk.getHeader()); + assertNotNull(chunk.getTrailer()); + assertNotNull(chunk.getSeparator()); + offset += chunk.getOnDiskSize(); + + chunk = cf.createChunk(data_a, offset); + assertNotNull(chunk.getHeader()); + assertNotNull(chunk.getTrailer()); + assertNotNull(chunk.getSeparator()); + offset += chunk.getOnDiskSize(); + + // Has a separator but no trailer + chunk = cf.createChunk(data_a, offset); + assertNotNull(chunk.getHeader()); + assertNull(chunk.getTrailer()); + assertNotNull(chunk.getSeparator()); + offset += chunk.getOnDiskSize(); + + chunk = cf.createChunk(data_a, offset); + assertNotNull(chunk.getHeader()); + assertNull(chunk.getTrailer()); + assertNotNull(chunk.getSeparator()); + offset += chunk.getOnDiskSize(); + + chunk = cf.createChunk(data_a, offset); + assertNotNull(chunk.getHeader()); + assertNull(chunk.getTrailer()); + assertNotNull(chunk.getSeparator()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/extractor/TestVisioExtractor.java b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/extractor/TestVisioExtractor.java index dc747a07a5..47afe3f74c 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/extractor/TestVisioExtractor.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/extractor/TestVisioExtractor.java @@ -33,70 +33,70 @@ import org.junit.jupiter.params.provider.ValueSource; public final class TestVisioExtractor { private static final POIDataSamples _dgTests = POIDataSamples.getDiagramInstance(); - private final String defFilename = "Test_Visio-Some_Random_Text.vsd"; - private final int defTextChunks = 5; - - /** - * Test the 3 different ways of creating one - */ - @Test - void testCreation() throws IOException { - try (VisioTextExtractor extractor1 = openExtractor(defFilename)) { - assertNotNull(extractor1); - assertNotNull(extractor1.getAllText()); - assertEquals(defTextChunks, extractor1.getAllText().length); - } - - try (InputStream is2 = _dgTests.openResourceAsStream(defFilename); - POIFSFileSystem poifs2 = new POIFSFileSystem(is2); - VisioTextExtractor extractor2 = new VisioTextExtractor(poifs2)) { - assertNotNull(extractor2); - assertNotNull(extractor2.getAllText()); - assertEquals(defTextChunks, extractor2.getAllText().length); - } + private final String defFilename = "Test_Visio-Some_Random_Text.vsd"; + private final int defTextChunks = 5; + + /** + * Test the 3 different ways of creating one + */ + @Test + void testCreation() throws IOException { + try (VisioTextExtractor extractor1 = openExtractor(defFilename)) { + assertNotNull(extractor1); + assertNotNull(extractor1.getAllText()); + assertEquals(defTextChunks, extractor1.getAllText().length); + } + + try (InputStream is2 = _dgTests.openResourceAsStream(defFilename); + POIFSFileSystem poifs2 = new POIFSFileSystem(is2); + VisioTextExtractor extractor2 = new VisioTextExtractor(poifs2)) { + assertNotNull(extractor2); + assertNotNull(extractor2.getAllText()); + assertEquals(defTextChunks, extractor2.getAllText().length); + } try (InputStream is3 = _dgTests.openResourceAsStream(defFilename); - POIFSFileSystem poifs3 = new POIFSFileSystem(is3); - HDGFDiagram hdgf3 = new HDGFDiagram(poifs3); - VisioTextExtractor extractor3 = new VisioTextExtractor(hdgf3)) { - assertNotNull(extractor3); - assertNotNull(extractor3.getAllText()); - assertEquals(defTextChunks, extractor3.getAllText().length); - } - } + POIFSFileSystem poifs3 = new POIFSFileSystem(is3); + HDGFDiagram hdgf3 = new HDGFDiagram(poifs3); + VisioTextExtractor extractor3 = new VisioTextExtractor(hdgf3)) { + assertNotNull(extractor3); + assertNotNull(extractor3.getAllText()); + assertEquals(defTextChunks, extractor3.getAllText().length); + } + } @Test - void testExtraction() throws Exception { - try (VisioTextExtractor extractor = openExtractor(defFilename)) { - - // Check the array fetch - String[] text = extractor.getAllText(); - assertNotNull(text); - assertEquals(defTextChunks, text.length); - - assertEquals("text\n", text[0]); - assertEquals("View\n", text[1]); - assertEquals("Test View\n", text[2]); - assertEquals("I am a test view\n", text[3]); - assertEquals("Some random text, on a page\n", text[4]); - - // And the all-in fetch - String textS = extractor.getText(); - assertEquals("text\nView\nTest View\nI am a test view\nSome random text, on a page\n", textS); - } - } + void testExtraction() throws Exception { + try (VisioTextExtractor extractor = openExtractor(defFilename)) { + + // Check the array fetch + String[] text = extractor.getAllText(); + assertNotNull(text); + assertEquals(defTextChunks, text.length); + + assertEquals("text\n", text[0]); + assertEquals("View\n", text[1]); + assertEquals("Test View\n", text[2]); + assertEquals("I am a test view\n", text[3]); + assertEquals("Some random text, on a page\n", text[4]); + + // And the all-in fetch + String textS = extractor.getText(); + assertEquals("text\nView\nTest View\nI am a test view\nSome random text, on a page\n", textS); + } + } @ParameterizedTest - @ValueSource(strings = { - "44594.vsd", "44594-2.vsd", - "ShortChunk1.vsd", "ShortChunk2.vsd", "ShortChunk3.vsd", - "NegativeChunkLength.vsd", "NegativeChunkLength2.vsd" - }) - void testProblemFiles(String file) throws Exception { - try (VisioTextExtractor ex = openExtractor(file)) { - assertNotNull(ex.getText()); - } - } + @ValueSource(strings = { + "44594.vsd", "44594-2.vsd", + "ShortChunk1.vsd", "ShortChunk2.vsd", "ShortChunk3.vsd", + "NegativeChunkLength.vsd", "NegativeChunkLength2.vsd" + }) + void testProblemFiles(String file) throws Exception { + try (VisioTextExtractor ex = openExtractor(file)) { + assertNotNull(ex.getText()); + } + } private VisioTextExtractor openExtractor(String fileName) throws IOException { try (InputStream is = _dgTests.openResourceAsStream(fileName)) { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/pointers/TestPointerFactory.java b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/pointers/TestPointerFactory.java index 3beedf60c0..641f8909b3 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/pointers/TestPointerFactory.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/pointers/TestPointerFactory.java @@ -34,32 +34,32 @@ public final class TestPointerFactory { 0x4d, 1, 0, 0 }; - // Type: 16 Addr: 0143aff4 Offset: 80 Len: 54 Format: 46 From: 8a94 - private static byte[] vp6_a = { - 22, 0, 0, 0, -12, -81, 67, 1, -128, 0, 0, 0, 84, 0, 0, 0, 70, 0 - }; - // Type: 17 Addr: 014fd84c Offset: d4 Len: 20 Format: 54 From: 8a94 - private static byte[] vp6_b = { - 23, 0, 0, 0, 76, -40, 79, 1, -44, 0, 0, 0, 32, 0, 0, 0, 84, 0 - }; - // Type: 17 Addr: 014fd8bc Offset: f8 Len: 20 Format: 54 From: 8a94 - private static byte[] vp6_c = { - 23, 0, 0, 0, -68, -40, 79, 1, -8, 0, 0, 0, 32, 0, 0, 0, 84, 0 - }; - // Type: ff Addr: 014fffac Offset: 0 Len: 0 Format: 60 From: 8a94 - private static byte[] vp6_d = { - -1, 0, 0, 0, -84, -1, 79, 1, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0 - }; - - @Test - void testCreateV4() { - PointerFactory pf = new PointerFactory(4); - assertThrows(IllegalArgumentException.class, () -> pf.createPointer(new byte[]{}, 0)); - } - - @Test - void testCreateV5() { - PointerFactory pf = new PointerFactory(5); + // Type: 16 Addr: 0143aff4 Offset: 80 Len: 54 Format: 46 From: 8a94 + private static byte[] vp6_a = { + 22, 0, 0, 0, -12, -81, 67, 1, -128, 0, 0, 0, 84, 0, 0, 0, 70, 0 + }; + // Type: 17 Addr: 014fd84c Offset: d4 Len: 20 Format: 54 From: 8a94 + private static byte[] vp6_b = { + 23, 0, 0, 0, 76, -40, 79, 1, -44, 0, 0, 0, 32, 0, 0, 0, 84, 0 + }; + // Type: 17 Addr: 014fd8bc Offset: f8 Len: 20 Format: 54 From: 8a94 + private static byte[] vp6_c = { + 23, 0, 0, 0, -68, -40, 79, 1, -8, 0, 0, 0, 32, 0, 0, 0, 84, 0 + }; + // Type: ff Addr: 014fffac Offset: 0 Len: 0 Format: 60 From: 8a94 + private static byte[] vp6_d = { + -1, 0, 0, 0, -84, -1, 79, 1, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0 + }; + + @Test + void testCreateV4() { + PointerFactory pf = new PointerFactory(4); + assertThrows(IllegalArgumentException.class, () -> pf.createPointer(new byte[]{}, 0)); + } + + @Test + void testCreateV5() { + PointerFactory pf = new PointerFactory(5); Pointer a = pf.createPointer(vp5_a, 0); assertEquals(0x14, a.getType()); @@ -75,84 +75,84 @@ public final class TestPointerFactory { assertTrue(a.destinationHasPointers()); assertEquals(16, a.getSizeInBytes()); - } - - @Test - void testCreateV6() { - PointerFactory pf = new PointerFactory(6); - - Pointer a = pf.createPointer(vp6_a, 0); - assertEquals(0x16, a.getType()); - assertEquals(0x0143aff4, a.getAddress()); - assertEquals(0x80, a.getOffset()); - assertEquals(0x54, a.getLength()); - assertEquals(0x46, a.getFormat()); - - assertTrue(a.destinationCompressed()); - assertTrue(a.destinationHasStrings()); - assertFalse(a.destinationHasChunks()); - assertFalse(a.destinationHasPointers()); - - assertEquals(18, a.getSizeInBytes()); - - - Pointer b = pf.createPointer(vp6_b, 0); - assertEquals(0x17, b.getType()); - assertEquals(0x014fd84c, b.getAddress()); - assertEquals(0xd4, b.getOffset()); - assertEquals(0x20, b.getLength()); - assertEquals(0x54, b.getFormat()); - - assertFalse(b.destinationCompressed()); - assertFalse(b.destinationHasStrings()); - assertFalse(b.destinationHasChunks()); - assertTrue(b.destinationHasPointers()); - - Pointer c = pf.createPointer(vp6_c, 0); - assertEquals(0x17, c.getType()); - assertEquals(0x014fd8bc, c.getAddress()); - assertEquals(0xf8, c.getOffset()); - assertEquals(0x20, c.getLength()); - assertEquals(0x54, c.getFormat()); - - assertFalse(c.destinationCompressed()); - assertFalse(c.destinationHasStrings()); - assertFalse(c.destinationHasChunks()); - assertTrue(c.destinationHasPointers()); - - // Type: ff Addr: 014fffac Offset: 0 Len: 0 Format: 60 From: 8a94 - Pointer d = pf.createPointer(vp6_d, 0); - assertEquals(0xff, d.getType()); - assertEquals(0x014fffac, d.getAddress()); - assertEquals(0x00, d.getOffset()); - assertEquals(0x00, d.getLength()); - assertEquals(0x60, d.getFormat()); - - assertFalse(d.destinationCompressed()); - assertFalse(d.destinationHasStrings()); - assertFalse(d.destinationHasChunks()); - assertFalse(d.destinationHasPointers()); - } - - @Test - void testCreateV6FromMid() { - PointerFactory pf = new PointerFactory(11); - - // Create a from part way down the byte stream - byte[] bytes = new byte[28]; - System.arraycopy(vp6_b, 0, bytes, 0, 10); - System.arraycopy(vp6_a, 0, bytes, 10, 18); - - Pointer a = pf.createPointer(bytes, 10); - assertEquals(0x16, a.getType()); - assertEquals(0x0143aff4, a.getAddress()); - assertEquals(0x80, a.getOffset()); - assertEquals(0x54, a.getLength()); - assertEquals(0x46, a.getFormat()); - - assertTrue(a.destinationCompressed()); - assertTrue(a.destinationHasStrings()); - assertFalse(a.destinationHasChunks()); - assertFalse(a.destinationHasPointers()); - } + } + + @Test + void testCreateV6() { + PointerFactory pf = new PointerFactory(6); + + Pointer a = pf.createPointer(vp6_a, 0); + assertEquals(0x16, a.getType()); + assertEquals(0x0143aff4, a.getAddress()); + assertEquals(0x80, a.getOffset()); + assertEquals(0x54, a.getLength()); + assertEquals(0x46, a.getFormat()); + + assertTrue(a.destinationCompressed()); + assertTrue(a.destinationHasStrings()); + assertFalse(a.destinationHasChunks()); + assertFalse(a.destinationHasPointers()); + + assertEquals(18, a.getSizeInBytes()); + + + Pointer b = pf.createPointer(vp6_b, 0); + assertEquals(0x17, b.getType()); + assertEquals(0x014fd84c, b.getAddress()); + assertEquals(0xd4, b.getOffset()); + assertEquals(0x20, b.getLength()); + assertEquals(0x54, b.getFormat()); + + assertFalse(b.destinationCompressed()); + assertFalse(b.destinationHasStrings()); + assertFalse(b.destinationHasChunks()); + assertTrue(b.destinationHasPointers()); + + Pointer c = pf.createPointer(vp6_c, 0); + assertEquals(0x17, c.getType()); + assertEquals(0x014fd8bc, c.getAddress()); + assertEquals(0xf8, c.getOffset()); + assertEquals(0x20, c.getLength()); + assertEquals(0x54, c.getFormat()); + + assertFalse(c.destinationCompressed()); + assertFalse(c.destinationHasStrings()); + assertFalse(c.destinationHasChunks()); + assertTrue(c.destinationHasPointers()); + + // Type: ff Addr: 014fffac Offset: 0 Len: 0 Format: 60 From: 8a94 + Pointer d = pf.createPointer(vp6_d, 0); + assertEquals(0xff, d.getType()); + assertEquals(0x014fffac, d.getAddress()); + assertEquals(0x00, d.getOffset()); + assertEquals(0x00, d.getLength()); + assertEquals(0x60, d.getFormat()); + + assertFalse(d.destinationCompressed()); + assertFalse(d.destinationHasStrings()); + assertFalse(d.destinationHasChunks()); + assertFalse(d.destinationHasPointers()); + } + + @Test + void testCreateV6FromMid() { + PointerFactory pf = new PointerFactory(11); + + // Create a from part way down the byte stream + byte[] bytes = new byte[28]; + System.arraycopy(vp6_b, 0, bytes, 0, 10); + System.arraycopy(vp6_a, 0, bytes, 10, 18); + + Pointer a = pf.createPointer(bytes, 10); + assertEquals(0x16, a.getType()); + assertEquals(0x0143aff4, a.getAddress()); + assertEquals(0x80, a.getOffset()); + assertEquals(0x54, a.getLength()); + assertEquals(0x46, a.getFormat()); + + assertTrue(a.destinationCompressed()); + assertTrue(a.destinationHasStrings()); + assertFalse(a.destinationHasChunks()); + assertFalse(a.destinationHasPointers()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamBasics.java b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamBasics.java index 847eaa05d1..1f79f2f967 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamBasics.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamBasics.java @@ -30,10 +30,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; public final class TestStreamBasics extends StreamTest { - private static byte[] compressedStream, uncompressedStream; + private static byte[] compressedStream, uncompressedStream; - @BeforeAll - public static void init() throws IOException { + @BeforeAll + public static void init() throws IOException { compressedStream = decompress( "H4sIAAAAAAAAAAFTAaz+e8QC6/ABAAC48/BO4PsBAAPr8AoFBOvwFQnr8Gfr8CLc/zQPRg94WA/5/u"+ "T3hRUALIYB/GgP6PMoniBOZr3//uJAKL2Pt3SeqwJCewltqwKnDsi7rbHe/XhuS/f2FPrn9Bbr8PSv"+ @@ -52,44 +52,44 @@ public final class TestStreamBasics extends StreamTest { "I0MRA8NiBuwuvAHES5xCGZPKGRgugP1lBAo951DGwEYGBj42kIg9yHaXUEa5DgYGLbAaF6DIFtdQxr"+ "ROmAgIAAD6SJPAdAIAAA==" ); - } - - - @Test - void testCompressedStream() { - // Create a fake pointer - Pointer ptr = new TestPointer(true, 0, compressedStream.length, -1, (short)-1); - // Now the stream - Stream stream = Stream.createStream(ptr, compressedStream, null, null); - - // Check - assertNotNull(stream.getPointer()); - assertNotNull(stream.getStore()); - assertTrue(stream.getStore() instanceof CompressedStreamStore); - assertTrue(stream instanceof UnknownStream); - - // Check the stream store - CompressedStreamStore ss = (CompressedStreamStore)stream.getStore(); - assertEquals(4, ss._getBlockHeader().length); - assertEquals(compressedStream.length, ss._getCompressedContents().length); - assertEquals(uncompressedStream.length, ss.getContents().length); - - for(int i=0; i<uncompressedStream.length; i++) { - assertEquals(uncompressedStream[i], ss.getContents()[i]); - } - } - - @Test + } + + + @Test + void testCompressedStream() { + // Create a fake pointer + Pointer ptr = new TestPointer(true, 0, compressedStream.length, -1, (short)-1); + // Now the stream + Stream stream = Stream.createStream(ptr, compressedStream, null, null); + + // Check + assertNotNull(stream.getPointer()); + assertNotNull(stream.getStore()); + assertTrue(stream.getStore() instanceof CompressedStreamStore); + assertTrue(stream instanceof UnknownStream); + + // Check the stream store + CompressedStreamStore ss = (CompressedStreamStore)stream.getStore(); + assertEquals(4, ss._getBlockHeader().length); + assertEquals(compressedStream.length, ss._getCompressedContents().length); + assertEquals(uncompressedStream.length, ss.getContents().length); + + for(int i=0; i<uncompressedStream.length; i++) { + assertEquals(uncompressedStream[i], ss.getContents()[i]); + } + } + + @Test void testUncompressedStream() { - // Create a fake pointer - Pointer ptr = new TestPointer(false, 0, uncompressedStream.length, -1, (short)-1); - // Now the stream - Stream stream = Stream.createStream(ptr, uncompressedStream, null, null); - - // Check - assertNotNull(stream.getPointer()); - assertNotNull(stream.getStore()); - assertFalse(stream.getStore() instanceof CompressedStreamStore); - assertTrue(stream instanceof UnknownStream); - } + // Create a fake pointer + Pointer ptr = new TestPointer(false, 0, uncompressedStream.length, -1, (short)-1); + // Now the stream + Stream stream = Stream.createStream(ptr, uncompressedStream, null, null); + + // Check + assertNotNull(stream.getPointer()); + assertNotNull(stream.getStore()); + assertFalse(stream.getStore() instanceof CompressedStreamStore); + assertTrue(stream instanceof UnknownStream); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamBugs.java b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamBugs.java index 47f33d0a15..f43d89a4f7 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamBugs.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamBugs.java @@ -38,76 +38,76 @@ import org.junit.jupiter.api.Test; * Tests for bugs with streams */ public final class TestStreamBugs extends StreamTest { - private byte[] contents; - private ChunkFactory chunkFactory; - private PointerFactory ptrFactory; - private POIFSFileSystem filesystem; + private byte[] contents; + private ChunkFactory chunkFactory; + private PointerFactory ptrFactory; + private POIFSFileSystem filesystem; - @BeforeEach + @BeforeEach void setUp() throws IOException { - ptrFactory = new PointerFactory(11); - chunkFactory = new ChunkFactory(11); + ptrFactory = new PointerFactory(11); + chunkFactory = new ChunkFactory(11); try (InputStream is = POIDataSamples.getDiagramInstance().openResourceAsStream("44594.vsd")) { - filesystem = new POIFSFileSystem(is); - } + filesystem = new POIFSFileSystem(is); + } - // Grab the document stream - try (InputStream is2 = filesystem.createDocumentInputStream("VisioDocument")) { - contents = IOUtils.toByteArray(is2); - } - } + // Grab the document stream + try (InputStream is2 = filesystem.createDocumentInputStream("VisioDocument")) { + contents = IOUtils.toByteArray(is2); + } + } - @Test + @Test void testGetTrailer() { - Pointer trailerPointer = ptrFactory.createPointer(contents, 0x24); - Stream s = Stream.createStream(trailerPointer, contents, chunkFactory, ptrFactory); - assertNotNull(s); - } + Pointer trailerPointer = ptrFactory.createPointer(contents, 0x24); + Stream s = Stream.createStream(trailerPointer, contents, chunkFactory, ptrFactory); + assertNotNull(s); + } - @SuppressWarnings("unused") + @SuppressWarnings("unused") void TOIMPLEMENTtestGetCertainChunks() { - int offsetA = 3708; - int offsetB = 3744; - } + int offsetA = 3708; + int offsetB = 3744; + } - @Test + @Test void testGetChildren() { - Pointer trailerPointer = ptrFactory.createPointer(contents, 0x24); - TrailerStream trailer = (TrailerStream) - Stream.createStream(trailerPointer, contents, chunkFactory, ptrFactory); - - // Get without recursing - Pointer[] ptrs = trailer.getChildPointers(); - for (Pointer ptr : ptrs) { - Stream.createStream(ptr, contents, chunkFactory, ptrFactory); - } - - // Get with recursing into chunks - for (Pointer ptr : ptrs) { - Stream stream = Stream.createStream(ptr, contents, chunkFactory, ptrFactory); - if(stream instanceof ChunkStream) { - ChunkStream cStream = (ChunkStream)stream; - assertDoesNotThrow(cStream::findChunks); - } - } - - // Get with recursing into chunks and pointers - for (Pointer ptr : ptrs) { - Stream stream = Stream.createStream(ptr, contents, chunkFactory, ptrFactory); - if(stream instanceof PointerContainingStream) { - PointerContainingStream pStream = (PointerContainingStream)stream; - assertDoesNotThrow(() -> pStream.findChildren(contents)); - } - } - - trailer.findChildren(contents); - } - - @Test + Pointer trailerPointer = ptrFactory.createPointer(contents, 0x24); + TrailerStream trailer = (TrailerStream) + Stream.createStream(trailerPointer, contents, chunkFactory, ptrFactory); + + // Get without recursing + Pointer[] ptrs = trailer.getChildPointers(); + for (Pointer ptr : ptrs) { + Stream.createStream(ptr, contents, chunkFactory, ptrFactory); + } + + // Get with recursing into chunks + for (Pointer ptr : ptrs) { + Stream stream = Stream.createStream(ptr, contents, chunkFactory, ptrFactory); + if(stream instanceof ChunkStream) { + ChunkStream cStream = (ChunkStream)stream; + assertDoesNotThrow(cStream::findChunks); + } + } + + // Get with recursing into chunks and pointers + for (Pointer ptr : ptrs) { + Stream stream = Stream.createStream(ptr, contents, chunkFactory, ptrFactory); + if(stream instanceof PointerContainingStream) { + PointerContainingStream pStream = (PointerContainingStream)stream; + assertDoesNotThrow(() -> pStream.findChildren(contents)); + } + } + + trailer.findChildren(contents); + } + + @Test void testOpen() throws IOException { - try (HDGFDiagram dia = new HDGFDiagram(filesystem)) { - assertEquals(20, dia.getTopLevelStreams().length); - } - } + try (HDGFDiagram dia = new HDGFDiagram(filesystem)) { + assertEquals(20, dia.getTopLevelStreams().length); + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamComplex.java b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamComplex.java index e65121ffaf..f4e9efe3c7 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamComplex.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hdgf/streams/TestStreamComplex.java @@ -37,246 +37,246 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public final class TestStreamComplex extends StreamTest { - private byte[] contents; - private final int trailerPointerAt = 0x24; - private final int trailerDataAt = 0x8a94; - private ChunkFactory chunkFactory; - private PointerFactory ptrFactory; + private byte[] contents; + private final int trailerPointerAt = 0x24; + private final int trailerDataAt = 0x8a94; + private ChunkFactory chunkFactory; + private PointerFactory ptrFactory; - @BeforeEach + @BeforeEach void setUp() throws IOException { - ptrFactory = new PointerFactory(11); - chunkFactory = new ChunkFactory(11); + ptrFactory = new PointerFactory(11); + chunkFactory = new ChunkFactory(11); InputStream is = POIDataSamples.getDiagramInstance().openResourceAsStream("Test_Visio-Some_Random_Text.vsd"); - POIFSFileSystem filesystem = new POIFSFileSystem(is); - is.close(); + POIFSFileSystem filesystem = new POIFSFileSystem(is); + is.close(); - // Grab the document stream - InputStream is2 = filesystem.createDocumentInputStream("VisioDocument"); - contents = IOUtils.toByteArray(is2); - is2.close(); + // Grab the document stream + InputStream is2 = filesystem.createDocumentInputStream("VisioDocument"); + contents = IOUtils.toByteArray(is2); + is2.close(); - filesystem.close(); - } + filesystem.close(); + } - /** - * Test creating the trailer, but not looking for children - */ - @Test + /** + * Test creating the trailer, but not looking for children + */ + @Test void testTrailer() { - // Find the trailer - Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); + // Find the trailer + Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); - assertEquals(20, trailerPtr.getType()); - assertEquals(trailerDataAt, trailerPtr.getOffset()); + assertEquals(20, trailerPtr.getType()); + assertEquals(trailerDataAt, trailerPtr.getOffset()); - Stream stream = Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); - assertTrue(stream instanceof TrailerStream); - TrailerStream ts = (TrailerStream)stream; + Stream stream = Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); + assertTrue(stream instanceof TrailerStream); + TrailerStream ts = (TrailerStream)stream; - assertNotNull(ts.getChildPointers()); - assertNull(ts.getPointedToStreams()); + assertNotNull(ts.getChildPointers()); + assertNull(ts.getPointedToStreams()); - assertEquals(20, ts.getChildPointers().length); - assertEquals(0x16, ts.getChildPointers()[0].getType()); - assertEquals(0x17, ts.getChildPointers()[1].getType()); - assertEquals(0x17, ts.getChildPointers()[2].getType()); - assertEquals(0xff, ts.getChildPointers()[3].getType()); - } + assertEquals(20, ts.getChildPointers().length); + assertEquals(0x16, ts.getChildPointers()[0].getType()); + assertEquals(0x17, ts.getChildPointers()[1].getType()); + assertEquals(0x17, ts.getChildPointers()[2].getType()); + assertEquals(0xff, ts.getChildPointers()[3].getType()); + } - @Test + @Test void testChunks() { - Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); - TrailerStream ts = (TrailerStream) - Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); - - // Should be 7th one - Pointer chunkPtr = ts.getChildPointers()[5]; - assertFalse(chunkPtr.destinationHasStrings()); - assertTrue(chunkPtr.destinationHasChunks()); - assertFalse(chunkPtr.destinationHasPointers()); - - Stream stream = Stream.createStream(chunkPtr, contents, chunkFactory, ptrFactory); - assertNotNull(stream); - assertTrue(stream instanceof ChunkStream); - - // Now find the chunks within it - ChunkStream cs = (ChunkStream)stream; - cs.findChunks(); - } - - @Test + Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); + TrailerStream ts = (TrailerStream) + Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); + + // Should be 7th one + Pointer chunkPtr = ts.getChildPointers()[5]; + assertFalse(chunkPtr.destinationHasStrings()); + assertTrue(chunkPtr.destinationHasChunks()); + assertFalse(chunkPtr.destinationHasPointers()); + + Stream stream = Stream.createStream(chunkPtr, contents, chunkFactory, ptrFactory); + assertNotNull(stream); + assertTrue(stream instanceof ChunkStream); + + // Now find the chunks within it + ChunkStream cs = (ChunkStream)stream; + cs.findChunks(); + } + + @Test void testStrings() { - Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); - TrailerStream ts = (TrailerStream) - Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); - - // Should be the 1st one - Pointer stringPtr = ts.getChildPointers()[0]; - assertTrue(stringPtr.destinationHasStrings()); - assertFalse(stringPtr.destinationHasChunks()); - assertFalse(stringPtr.destinationHasPointers()); - - Stream stream = Stream.createStream(stringPtr, contents, chunkFactory, ptrFactory); - assertNotNull(stream); - assertTrue(stream instanceof StringsStream); - } - - @Test + Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); + TrailerStream ts = (TrailerStream) + Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); + + // Should be the 1st one + Pointer stringPtr = ts.getChildPointers()[0]; + assertTrue(stringPtr.destinationHasStrings()); + assertFalse(stringPtr.destinationHasChunks()); + assertFalse(stringPtr.destinationHasPointers()); + + Stream stream = Stream.createStream(stringPtr, contents, chunkFactory, ptrFactory); + assertNotNull(stream); + assertTrue(stream instanceof StringsStream); + } + + @Test void testPointerToStrings() { - // The stream at 0x347f has strings - // The stream at 0x4312 has a pointer to 0x347f - // The stream at 0x44d3 has a pointer to 0x4312 - // (it's the 2nd one of 3, and the block is compressed) - - TestPointer ptr44d3 = new TestPointer(true, 0x44d3, 0x51, 0x4e, (short)0x56); - ptr44d3.hasPointers = true; - PointerContainingStream s44d3 = (PointerContainingStream) - Stream.createStream(ptr44d3, contents, chunkFactory, ptrFactory); - - // Type: 0d Addr: 014ff644 Offset: 4312 Len: 48 Format: 54 From: 44d3 - Pointer ptr4312 = s44d3.getChildPointers()[1]; - assertEquals(0x0d, ptr4312.getType()); - assertEquals(0x4312, ptr4312.getOffset()); - assertEquals(0x48, ptr4312.getLength()); - assertEquals(0x54, ptr4312.getFormat()); - assertTrue(ptr4312.destinationHasPointers()); - assertFalse(ptr4312.destinationHasStrings()); - - PointerContainingStream s4312 = (PointerContainingStream) - Stream.createStream(ptr4312, contents, chunkFactory, ptrFactory); - - // Check it has 0x347f - // Type: 1f Addr: 01540004 Offset: 347f Len: 8e8 Format: 46 From: 4312 - assertEquals(2, s4312.getChildPointers().length); - Pointer ptr347f = s4312.getChildPointers()[0]; - assertEquals(0x1f, ptr347f.getType()); - assertEquals(0x347f, ptr347f.getOffset()); - assertEquals(0x8e8, ptr347f.getLength()); - assertEquals(0x46, ptr347f.getFormat()); - assertFalse(ptr347f.destinationHasPointers()); - assertTrue(ptr347f.destinationHasStrings()); - - // Find the children of 0x4312 - assertNull(s4312.getPointedToStreams()); - s4312.findChildren(contents); - // Should have two, both strings - assertNotNull(s4312.getPointedToStreams()); - assertEquals(2, s4312.getPointedToStreams().length); - assertTrue(s4312.getPointedToStreams()[0] instanceof StringsStream); - assertTrue(s4312.getPointedToStreams()[1] instanceof StringsStream); - } - - @Test + // The stream at 0x347f has strings + // The stream at 0x4312 has a pointer to 0x347f + // The stream at 0x44d3 has a pointer to 0x4312 + // (it's the 2nd one of 3, and the block is compressed) + + TestPointer ptr44d3 = new TestPointer(true, 0x44d3, 0x51, 0x4e, (short)0x56); + ptr44d3.hasPointers = true; + PointerContainingStream s44d3 = (PointerContainingStream) + Stream.createStream(ptr44d3, contents, chunkFactory, ptrFactory); + + // Type: 0d Addr: 014ff644 Offset: 4312 Len: 48 Format: 54 From: 44d3 + Pointer ptr4312 = s44d3.getChildPointers()[1]; + assertEquals(0x0d, ptr4312.getType()); + assertEquals(0x4312, ptr4312.getOffset()); + assertEquals(0x48, ptr4312.getLength()); + assertEquals(0x54, ptr4312.getFormat()); + assertTrue(ptr4312.destinationHasPointers()); + assertFalse(ptr4312.destinationHasStrings()); + + PointerContainingStream s4312 = (PointerContainingStream) + Stream.createStream(ptr4312, contents, chunkFactory, ptrFactory); + + // Check it has 0x347f + // Type: 1f Addr: 01540004 Offset: 347f Len: 8e8 Format: 46 From: 4312 + assertEquals(2, s4312.getChildPointers().length); + Pointer ptr347f = s4312.getChildPointers()[0]; + assertEquals(0x1f, ptr347f.getType()); + assertEquals(0x347f, ptr347f.getOffset()); + assertEquals(0x8e8, ptr347f.getLength()); + assertEquals(0x46, ptr347f.getFormat()); + assertFalse(ptr347f.destinationHasPointers()); + assertTrue(ptr347f.destinationHasStrings()); + + // Find the children of 0x4312 + assertNull(s4312.getPointedToStreams()); + s4312.findChildren(contents); + // Should have two, both strings + assertNotNull(s4312.getPointedToStreams()); + assertEquals(2, s4312.getPointedToStreams().length); + assertTrue(s4312.getPointedToStreams()[0] instanceof StringsStream); + assertTrue(s4312.getPointedToStreams()[1] instanceof StringsStream); + } + + @Test void testTrailerContents() { - Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); - TrailerStream ts = (TrailerStream) - Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); + Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); + TrailerStream ts = (TrailerStream) + Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); - assertNotNull(ts.getChildPointers()); - assertNull(ts.getPointedToStreams()); - assertEquals(20, ts.getChildPointers().length); + assertNotNull(ts.getChildPointers()); + assertNull(ts.getPointedToStreams()); + assertEquals(20, ts.getChildPointers().length); - ts.findChildren(contents); + ts.findChildren(contents); - assertNotNull(ts.getChildPointers()); - assertNotNull(ts.getPointedToStreams()); - assertEquals(20, ts.getChildPointers().length); - assertEquals(20, ts.getPointedToStreams().length); + assertNotNull(ts.getChildPointers()); + assertNotNull(ts.getPointedToStreams()); + assertEquals(20, ts.getChildPointers().length); + assertEquals(20, ts.getPointedToStreams().length); - // Step down: - // 8 -> 4 -> 5 -> 1 -> 0 == String - assertNotNull(ts.getPointedToStreams()[8]); - assertTrue(ts.getPointedToStreams()[8] instanceof PointerContainingStream); + // Step down: + // 8 -> 4 -> 5 -> 1 -> 0 == String + assertNotNull(ts.getPointedToStreams()[8]); + assertTrue(ts.getPointedToStreams()[8] instanceof PointerContainingStream); - PointerContainingStream s8 = - (PointerContainingStream)ts.getPointedToStreams()[8]; - assertNotNull(s8.getPointedToStreams()); + PointerContainingStream s8 = + (PointerContainingStream)ts.getPointedToStreams()[8]; + assertNotNull(s8.getPointedToStreams()); - assertNotNull(s8.getPointedToStreams()[4]); - assertTrue(s8.getPointedToStreams()[4] instanceof PointerContainingStream); + assertNotNull(s8.getPointedToStreams()[4]); + assertTrue(s8.getPointedToStreams()[4] instanceof PointerContainingStream); - PointerContainingStream s84 = - (PointerContainingStream)s8.getPointedToStreams()[4]; - assertNotNull(s84.getPointedToStreams()); + PointerContainingStream s84 = + (PointerContainingStream)s8.getPointedToStreams()[4]; + assertNotNull(s84.getPointedToStreams()); - assertNotNull(s84.getPointedToStreams()[5]); - assertTrue(s84.getPointedToStreams()[5] instanceof PointerContainingStream); + assertNotNull(s84.getPointedToStreams()[5]); + assertTrue(s84.getPointedToStreams()[5] instanceof PointerContainingStream); - PointerContainingStream s845 = - (PointerContainingStream)s84.getPointedToStreams()[5]; - assertNotNull(s845.getPointedToStreams()); + PointerContainingStream s845 = + (PointerContainingStream)s84.getPointedToStreams()[5]; + assertNotNull(s845.getPointedToStreams()); - assertNotNull(s845.getPointedToStreams()[1]); - assertTrue(s845.getPointedToStreams()[1] instanceof PointerContainingStream); + assertNotNull(s845.getPointedToStreams()[1]); + assertTrue(s845.getPointedToStreams()[1] instanceof PointerContainingStream); - PointerContainingStream s8451 = - (PointerContainingStream)s845.getPointedToStreams()[1]; - assertNotNull(s8451.getPointedToStreams()); + PointerContainingStream s8451 = + (PointerContainingStream)s845.getPointedToStreams()[1]; + assertNotNull(s8451.getPointedToStreams()); - assertNotNull(s8451.getPointedToStreams()[0]); - assertTrue(s8451.getPointedToStreams()[0] instanceof StringsStream); - assertTrue(s8451.getPointedToStreams()[1] instanceof StringsStream); - } + assertNotNull(s8451.getPointedToStreams()[0]); + assertTrue(s8451.getPointedToStreams()[0] instanceof StringsStream); + assertTrue(s8451.getPointedToStreams()[1] instanceof StringsStream); + } - @Test + @Test void testChunkWithText() { - // Parent ChunkStream is at 0x7194 - // This is one of the last children of the trailer - Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); - TrailerStream ts = (TrailerStream) - Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); - - ts.findChildren(contents); - - assertNotNull(ts.getChildPointers()); - assertNotNull(ts.getPointedToStreams()); - assertEquals(20, ts.getChildPointers().length); - assertEquals(20, ts.getPointedToStreams().length); - - assertEquals(0x7194, ts.getChildPointers()[13].getOffset()); - assertEquals(0x7194, ts.getPointedToStreams()[13].getPointer().getOffset()); - - PointerContainingStream ps7194 = (PointerContainingStream) - ts.getPointedToStreams()[13]; - - // First child is at 0x64b3 - assertEquals(0x64b3, ps7194.getChildPointers()[0].getOffset()); - assertEquals(0x64b3, ps7194.getPointedToStreams()[0].getPointer().getOffset()); - - ChunkStream cs = (ChunkStream)ps7194.getPointedToStreams()[0]; - - // Should be 26bc bytes un-compressed - assertEquals(0x26bc, cs.getStore().getContents().length); - // And should have lots of children - assertEquals(131, cs.getChunks().length); - - // One of which is Text - boolean hasText = false; - for(int i=0; i<cs.getChunks().length; i++) { - if(cs.getChunks()[i].getName().equals("Text")) { - hasText = true; - } - } - assertTrue(hasText); - // Which is the 72nd command - assertEquals("Text", cs.getChunks()[72].getName()); - - Chunk text = cs.getChunks()[72]; - assertEquals("Text", text.getName()); - - // Which contains our text - assertEquals(1, text.getCommands().length); - assertEquals("Test View\n", text.getCommands()[0].getValue()); - - - // Almost at the end is some more text - assertEquals("Text", cs.getChunks()[128].getName()); - text = cs.getChunks()[128]; - assertEquals("Text", text.getName()); - - assertEquals(1, text.getCommands().length); - assertEquals("Some random text, on a page\n", text.getCommands()[0].getValue()); - } + // Parent ChunkStream is at 0x7194 + // This is one of the last children of the trailer + Pointer trailerPtr = ptrFactory.createPointer(contents, trailerPointerAt); + TrailerStream ts = (TrailerStream) + Stream.createStream(trailerPtr, contents, chunkFactory, ptrFactory); + + ts.findChildren(contents); + + assertNotNull(ts.getChildPointers()); + assertNotNull(ts.getPointedToStreams()); + assertEquals(20, ts.getChildPointers().length); + assertEquals(20, ts.getPointedToStreams().length); + + assertEquals(0x7194, ts.getChildPointers()[13].getOffset()); + assertEquals(0x7194, ts.getPointedToStreams()[13].getPointer().getOffset()); + + PointerContainingStream ps7194 = (PointerContainingStream) + ts.getPointedToStreams()[13]; + + // First child is at 0x64b3 + assertEquals(0x64b3, ps7194.getChildPointers()[0].getOffset()); + assertEquals(0x64b3, ps7194.getPointedToStreams()[0].getPointer().getOffset()); + + ChunkStream cs = (ChunkStream)ps7194.getPointedToStreams()[0]; + + // Should be 26bc bytes un-compressed + assertEquals(0x26bc, cs.getStore().getContents().length); + // And should have lots of children + assertEquals(131, cs.getChunks().length); + + // One of which is Text + boolean hasText = false; + for(int i=0; i<cs.getChunks().length; i++) { + if(cs.getChunks()[i].getName().equals("Text")) { + hasText = true; + } + } + assertTrue(hasText); + // Which is the 72nd command + assertEquals("Text", cs.getChunks()[72].getName()); + + Chunk text = cs.getChunks()[72]; + assertEquals("Text", text.getName()); + + // Which contains our text + assertEquals(1, text.getCommands().length); + assertEquals("Test View\n", text.getCommands()[0].getValue()); + + + // Almost at the end is some more text + assertEquals("Text", cs.getChunks()[128].getName()); + text = cs.getChunks()[128]; + assertEquals("Text", text.getName()); + + assertEquals(1, text.getCommands().length); + assertEquals("Some random text, on a page\n", text.getCommands()[0].getValue()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hmef/attribute/TestTNEFAttributes.java b/poi-scratchpad/src/test/java/org/apache/poi/hmef/attribute/TestTNEFAttributes.java index c103bbc9e0..9e30526999 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hmef/attribute/TestTNEFAttributes.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hmef/attribute/TestTNEFAttributes.java @@ -136,7 +136,7 @@ public final class TestTNEFAttributes { assertEquals(TNEFStringAttribute.class, attr.getClass()); // It is a null terminated string - assertEquals("quick.doc\u0000", new String(attr.getData(), StandardCharsets.US_ASCII)); + assertEquals("quick.doc\u0000", new String(attr.getData(), StandardCharsets.US_ASCII)); // But when we ask for the string, that is sorted for us TNEFStringAttribute str = (TNEFStringAttribute) attr; diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hpbf/TestHPBFDocument.java b/poi-scratchpad/src/test/java/org/apache/poi/hpbf/TestHPBFDocument.java index eccb4ce8ec..681941e9bd 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hpbf/TestHPBFDocument.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hpbf/TestHPBFDocument.java @@ -31,34 +31,34 @@ public final class TestHPBFDocument { private static final POIDataSamples _samples = POIDataSamples.getPublisherInstance(); @Test - void testOpen() throws IOException { - InputStream is = _samples.openResourceAsStream("Sample.pub"); - HPBFDocument doc = new HPBFDocument(is); - is.close(); - assertNotNull(doc); - doc.close(); - } + void testOpen() throws IOException { + InputStream is = _samples.openResourceAsStream("Sample.pub"); + HPBFDocument doc = new HPBFDocument(is); + is.close(); + assertNotNull(doc); + doc.close(); + } @Test - void testBits() throws IOException { + void testBits() throws IOException { InputStream is = _samples.openResourceAsStream("Sample.pub"); - HPBFDocument doc = new HPBFDocument(is); + HPBFDocument doc = new HPBFDocument(is); is.close(); - assertNotNull(doc.getMainContents()); - assertNotNull(doc.getQuillContents()); - assertNotNull(doc.getEscherStm()); - assertNotNull(doc.getEscherDelayStm()); + assertNotNull(doc.getMainContents()); + assertNotNull(doc.getQuillContents()); + assertNotNull(doc.getEscherStm()); + assertNotNull(doc.getEscherDelayStm()); - assertTrue(doc.getMainContents().getData().length > 0); - assertTrue(doc.getQuillContents().getData().length > 0); - assertTrue(doc.getEscherStm().getData().length > 0); + assertTrue(doc.getMainContents().getData().length > 0); + assertTrue(doc.getQuillContents().getData().length > 0); + assertTrue(doc.getEscherStm().getData().length > 0); assertEquals(0, doc.getEscherDelayStm().getData().length); doc.close(); - } + } - // TODO -// void testWrite() throws Exception { -// } + // TODO +// void testWrite() throws Exception { +// } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hpbf/model/TestEscherParts.java b/poi-scratchpad/src/test/java/org/apache/poi/hpbf/model/TestEscherParts.java index c96fdbda80..dc52a8c0db 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hpbf/model/TestEscherParts.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hpbf/model/TestEscherParts.java @@ -31,55 +31,55 @@ public final class TestEscherParts { private static final POIDataSamples _samples = POIDataSamples.getPublisherInstance(); @Test - void testBasics() throws IOException { + void testBasics() throws IOException { InputStream is = _samples.openResourceAsStream("Sample.pub"); - HPBFDocument doc = new HPBFDocument(is); - is.close(); + HPBFDocument doc = new HPBFDocument(is); + is.close(); - EscherStm es = doc.getEscherStm(); - EscherDelayStm eds = doc.getEscherDelayStm(); + EscherStm es = doc.getEscherStm(); + EscherDelayStm eds = doc.getEscherDelayStm(); - assertNotNull(es); - assertNotNull(eds); + assertNotNull(es); + assertNotNull(eds); - assertEquals(13, es.getEscherRecords().length); - assertEquals(0, eds.getEscherRecords().length); + assertEquals(13, es.getEscherRecords().length); + assertEquals(0, eds.getEscherRecords().length); - // TODO - check the contents - doc.close(); - } + // TODO - check the contents + doc.close(); + } @Test void testComplex() throws Exception { InputStream is = _samples.openResourceAsStream("SampleBrochure.pub"); - HPBFDocument doc1 = new HPBFDocument(is); - is.close(); + HPBFDocument doc1 = new HPBFDocument(is); + is.close(); - EscherStm es = doc1.getEscherStm(); - EscherDelayStm eds = doc1.getEscherDelayStm(); + EscherStm es = doc1.getEscherStm(); + EscherDelayStm eds = doc1.getEscherDelayStm(); - assertNotNull(es); - assertNotNull(eds); + assertNotNull(es); + assertNotNull(eds); - assertEquals(30, es.getEscherRecords().length); - assertEquals(19, eds.getEscherRecords().length); + assertEquals(30, es.getEscherRecords().length); + assertEquals(19, eds.getEscherRecords().length); - // TODO - check contents - doc1.close(); + // TODO - check contents + doc1.close(); - // Now do another complex file - InputStream is2 = _samples.openResourceAsStream("SampleNewsletter.pub"); + // Now do another complex file + InputStream is2 = _samples.openResourceAsStream("SampleNewsletter.pub"); HPBFDocument doc2 = new HPBFDocument(is2); - is2.close(); + is2.close(); - es = doc2.getEscherStm(); - eds = doc2.getEscherDelayStm(); + es = doc2.getEscherStm(); + eds = doc2.getEscherDelayStm(); - assertNotNull(es); - assertNotNull(eds); + assertNotNull(es); + assertNotNull(eds); - assertEquals(51, es.getEscherRecords().length); - assertEquals(92, eds.getEscherRecords().length); - doc2.close(); - } + assertEquals(51, es.getEscherRecords().length); + assertEquals(92, eds.getEscherRecords().length); + doc2.close(); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hpbf/model/TestQuillContents.java b/poi-scratchpad/src/test/java/org/apache/poi/hpbf/model/TestQuillContents.java index 8fd5a6bf3b..0c7a647ea7 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hpbf/model/TestQuillContents.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hpbf/model/TestQuillContents.java @@ -40,409 +40,409 @@ public final class TestQuillContents { @Test void testBasics() throws IOException { - HPBFDocument doc = new HPBFDocument( - _samples.openResourceAsStream("Sample.pub") - ); - - QuillContents qc = doc.getQuillContents(); - assertEquals(20, qc.getBits().length); - for(int i=0; i<19; i++) { - assertNotNull(qc.getBits()[i]); - } - // Last one is blank - assertNull(qc.getBits()[19]); - - // Should be text, then three STSHs - assertEquals("TEXT", qc.getBits()[0].getThingType()); - assertEquals("TEXT", qc.getBits()[0].getBitType()); - assertEquals(0, qc.getBits()[0].getOptA()); - - assertEquals("STSH", qc.getBits()[1].getThingType()); - assertEquals("STSH", qc.getBits()[1].getBitType()); - assertEquals(0, qc.getBits()[1].getOptA()); - - assertEquals("STSH", qc.getBits()[2].getThingType()); - assertEquals("STSH", qc.getBits()[2].getBitType()); - assertEquals(1, qc.getBits()[2].getOptA()); - - assertEquals("STSH", qc.getBits()[3].getThingType()); - assertEquals("STSH", qc.getBits()[3].getBitType()); - assertEquals(2, qc.getBits()[3].getOptA()); - - doc.close(); - } + HPBFDocument doc = new HPBFDocument( + _samples.openResourceAsStream("Sample.pub") + ); + + QuillContents qc = doc.getQuillContents(); + assertEquals(20, qc.getBits().length); + for(int i=0; i<19; i++) { + assertNotNull(qc.getBits()[i]); + } + // Last one is blank + assertNull(qc.getBits()[19]); + + // Should be text, then three STSHs + assertEquals("TEXT", qc.getBits()[0].getThingType()); + assertEquals("TEXT", qc.getBits()[0].getBitType()); + assertEquals(0, qc.getBits()[0].getOptA()); + + assertEquals("STSH", qc.getBits()[1].getThingType()); + assertEquals("STSH", qc.getBits()[1].getBitType()); + assertEquals(0, qc.getBits()[1].getOptA()); + + assertEquals("STSH", qc.getBits()[2].getThingType()); + assertEquals("STSH", qc.getBits()[2].getBitType()); + assertEquals(1, qc.getBits()[2].getOptA()); + + assertEquals("STSH", qc.getBits()[3].getThingType()); + assertEquals("STSH", qc.getBits()[3].getBitType()); + assertEquals(2, qc.getBits()[3].getOptA()); + + doc.close(); + } @Test - void testText() throws IOException { - HPBFDocument doc = new HPBFDocument( + void testText() throws IOException { + HPBFDocument doc = new HPBFDocument( _samples.openResourceAsStream("Sample.pub") - ); + ); - QuillContents qc = doc.getQuillContents(); - assertEquals(20, qc.getBits().length); + QuillContents qc = doc.getQuillContents(); + assertEquals(20, qc.getBits().length); - QCTextBit text = (QCTextBit)qc.getBits()[0]; - String t = text.getText(); - assertStartsWith(t, "This is some text on the first page"); - assertEndsWith(t, "Within doc to page 1\r"); + QCTextBit text = (QCTextBit)qc.getBits()[0]; + String t = text.getText(); + assertStartsWith(t, "This is some text on the first page"); + assertEndsWith(t, "Within doc to page 1\r"); doc.close(); - } + } @Test - void testPLC() throws IOException { - HPBFDocument doc = new HPBFDocument( + void testPLC() throws IOException { + HPBFDocument doc = new HPBFDocument( _samples.openResourceAsStream("Simple.pub") - ); - - QuillContents qc = doc.getQuillContents(); - assertEquals(20, qc.getBits().length); - - assertTrue(qc.getBits()[9] instanceof Type4); - assertTrue(qc.getBits()[10] instanceof Type4); - assertTrue(qc.getBits()[12] instanceof Type8); - - Type4 plc9 = (Type4)qc.getBits()[9]; - Type4 plc10 = (Type4)qc.getBits()[10]; - Type8 plc12 = (Type8)qc.getBits()[12]; - - - assertEquals(1, plc9.getNumberOfPLCs()); - assertEquals(4, plc9.getPreData().length); - assertEquals(1, plc9.getPlcValA().length); - assertEquals(1, plc9.getPlcValB().length); - - assertEquals(0, plc9.getPreData()[0]); - assertEquals(0, plc9.getPreData()[1]); - assertEquals(0, plc9.getPreData()[2]); - assertEquals(0, plc9.getPreData()[3]); - assertEquals(0x356, plc9.getPlcValA()[0]); - assertEquals(0x600, plc9.getPlcValB()[0]); - - - assertEquals(1, plc10.getNumberOfPLCs()); - assertEquals(4, plc10.getPreData().length); - assertEquals(1, plc10.getPlcValA().length); - assertEquals(1, plc10.getPlcValB().length); - - assertEquals(0, plc10.getPreData()[0]); - assertEquals(0, plc10.getPreData()[1]); - assertEquals(0, plc10.getPreData()[2]); - assertEquals(0, plc10.getPreData()[3]); - assertEquals(0x356, plc10.getPlcValA()[0]); - assertEquals(0x800, plc10.getPlcValB()[0]); - - assertEquals(2, plc12.getNumberOfPLCs()); - assertEquals(7, plc12.getPreData().length); - assertEquals(2, plc12.getPlcValA().length); - assertEquals(2, plc12.getPlcValB().length); - - assertEquals(0xff, plc12.getPreData()[0]); - assertEquals(0, plc12.getPreData()[1]); - assertEquals(0x3d, plc12.getPreData()[2]); - assertEquals(0, plc12.getPreData()[3]); - assertEquals(0x6e, plc12.getPreData()[4]); - assertEquals(0, plc12.getPreData()[5]); - assertEquals(0, plc12.getPreData()[6]); - assertEquals(0xa0000, plc12.getPlcValA()[0]); - assertEquals(0x22000000, plc12.getPlcValB()[0]); - assertEquals(0x05, plc12.getPlcValA()[1]); - assertEquals(0x04, plc12.getPlcValB()[1]); - - doc.close(); - } + ); + + QuillContents qc = doc.getQuillContents(); + assertEquals(20, qc.getBits().length); + + assertTrue(qc.getBits()[9] instanceof Type4); + assertTrue(qc.getBits()[10] instanceof Type4); + assertTrue(qc.getBits()[12] instanceof Type8); + + Type4 plc9 = (Type4)qc.getBits()[9]; + Type4 plc10 = (Type4)qc.getBits()[10]; + Type8 plc12 = (Type8)qc.getBits()[12]; + + + assertEquals(1, plc9.getNumberOfPLCs()); + assertEquals(4, plc9.getPreData().length); + assertEquals(1, plc9.getPlcValA().length); + assertEquals(1, plc9.getPlcValB().length); + + assertEquals(0, plc9.getPreData()[0]); + assertEquals(0, plc9.getPreData()[1]); + assertEquals(0, plc9.getPreData()[2]); + assertEquals(0, plc9.getPreData()[3]); + assertEquals(0x356, plc9.getPlcValA()[0]); + assertEquals(0x600, plc9.getPlcValB()[0]); + + + assertEquals(1, plc10.getNumberOfPLCs()); + assertEquals(4, plc10.getPreData().length); + assertEquals(1, plc10.getPlcValA().length); + assertEquals(1, plc10.getPlcValB().length); + + assertEquals(0, plc10.getPreData()[0]); + assertEquals(0, plc10.getPreData()[1]); + assertEquals(0, plc10.getPreData()[2]); + assertEquals(0, plc10.getPreData()[3]); + assertEquals(0x356, plc10.getPlcValA()[0]); + assertEquals(0x800, plc10.getPlcValB()[0]); + + assertEquals(2, plc12.getNumberOfPLCs()); + assertEquals(7, plc12.getPreData().length); + assertEquals(2, plc12.getPlcValA().length); + assertEquals(2, plc12.getPlcValB().length); + + assertEquals(0xff, plc12.getPreData()[0]); + assertEquals(0, plc12.getPreData()[1]); + assertEquals(0x3d, plc12.getPreData()[2]); + assertEquals(0, plc12.getPreData()[3]); + assertEquals(0x6e, plc12.getPreData()[4]); + assertEquals(0, plc12.getPreData()[5]); + assertEquals(0, plc12.getPreData()[6]); + assertEquals(0xa0000, plc12.getPlcValA()[0]); + assertEquals(0x22000000, plc12.getPlcValB()[0]); + assertEquals(0x05, plc12.getPlcValA()[1]); + assertEquals(0x04, plc12.getPlcValB()[1]); + + doc.close(); + } @SuppressWarnings("unused") @Test - void testComplexPLC() throws IOException { - HPBFDocument doc = new HPBFDocument( + void testComplexPLC() throws IOException { + HPBFDocument doc = new HPBFDocument( _samples.openResourceAsStream("Sample.pub") - ); - - QuillContents qc = doc.getQuillContents(); - assertEquals(20, qc.getBits().length); - - assertTrue(qc.getBits()[10] instanceof Type4); - assertTrue(qc.getBits()[11] instanceof Type4); - assertTrue(qc.getBits()[13] instanceof Type0); - assertTrue(qc.getBits()[14] instanceof Type12); - assertTrue(qc.getBits()[15] instanceof Type12); - assertTrue(qc.getBits()[16] instanceof Type8); - - Type4 plc10 = (Type4)qc.getBits()[10]; - Type4 plc11 = (Type4)qc.getBits()[11]; - Type0 plc13 = (Type0)qc.getBits()[13]; - Type12 plc14 = (Type12)qc.getBits()[14]; - Type12 plc15 = (Type12)qc.getBits()[15]; - Type8 plc16 = (Type8)qc.getBits()[16]; - - - assertEquals(1, plc10.getNumberOfPLCs()); - assertEquals(4, plc10.getPreData().length); - assertEquals(1, plc10.getPlcValA().length); - assertEquals(1, plc10.getPlcValB().length); - - assertEquals(0, plc10.getPreData()[0]); - assertEquals(0, plc10.getPreData()[1]); - assertEquals(0, plc10.getPreData()[2]); - assertEquals(0, plc10.getPreData()[3]); - assertEquals(0x5d0, plc10.getPlcValA()[0]); - assertEquals(0x800, plc10.getPlcValB()[0]); - - - assertEquals(2, plc11.getNumberOfPLCs()); - assertEquals(4, plc11.getPreData().length); - assertEquals(2, plc11.getPlcValA().length); - assertEquals(2, plc11.getPlcValB().length); - - assertEquals(0, plc11.getPreData()[0]); - assertEquals(0, plc11.getPreData()[1]); - assertEquals(0, plc11.getPreData()[2]); - assertEquals(0, plc11.getPreData()[3]); - assertEquals(0x53a, plc11.getPlcValA()[0]); - assertEquals(0x5d0, plc11.getPlcValB()[0]); - assertEquals(0xa00, plc11.getPlcValA()[1]); - assertEquals(0xc00, plc11.getPlcValB()[1]); - - - assertEquals(5, plc13.getNumberOfPLCs()); - assertEquals(4, plc13.getPreData().length); - assertEquals(5, plc13.getPlcValA().length); - assertEquals(5, plc13.getPlcValB().length); - - assertEquals(0xff00, plc13.getPreData()[0]); - assertEquals(0, plc13.getPreData()[1]); - assertEquals(0xf, plc13.getPreData()[2]); - assertEquals(0, plc13.getPreData()[3]); - assertEquals(0x19, plc13.getPlcValA()[0]); - assertEquals(0x00, plc13.getPlcValB()[0]); - assertEquals(0x27, plc13.getPlcValA()[1]); - assertEquals(0x00, plc13.getPlcValB()[1]); - assertEquals(0x36, plc13.getPlcValA()[2]); - assertEquals(0x00, plc13.getPlcValB()[2]); - assertEquals(0x42, plc13.getPlcValA()[3]); - assertEquals(0x00, plc13.getPlcValB()[3]); - assertEquals(0x50, plc13.getPlcValA()[4]); - assertEquals(0x00, plc13.getPlcValB()[4]); - - - // TODO - test the type 12s - - - assertEquals(6, plc16.getNumberOfPLCs()); - assertEquals(7, plc16.getPreData().length); - assertEquals(6, plc16.getPlcValA().length); - assertEquals(6, plc16.getPlcValB().length); - - assertEquals(0xff, plc16.getPreData()[0]); - assertEquals(0, plc16.getPreData()[1]); - assertEquals(0x56, plc16.getPreData()[2]); - assertEquals(0, plc16.getPreData()[3]); - assertEquals(0x62, plc16.getPreData()[4]); - assertEquals(0, plc16.getPreData()[5]); - assertEquals(0x3e, plc16.getPreData()[6]); - assertEquals(0x500000, plc16.getPlcValA()[0]); - assertEquals(0x570000, plc16.getPlcValB()[0]); - assertEquals(0x4b0000, plc16.getPlcValA()[1]); - assertEquals(0x000000, plc16.getPlcValB()[1]); - assertEquals(0x0a0000, plc16.getPlcValA()[2]); - assertEquals(0x22000000, plc16.getPlcValB()[2]); - assertEquals(0x000005, plc16.getPlcValA()[3]); - assertEquals(0x000004, plc16.getPlcValB()[3]); - assertEquals(0x000004, plc16.getPlcValA()[4]); - assertEquals(0x000004, plc16.getPlcValB()[4]); - assertEquals(0x000004, plc16.getPlcValA()[5]); - assertEquals(0x000004, plc16.getPlcValB()[5]); + ); + + QuillContents qc = doc.getQuillContents(); + assertEquals(20, qc.getBits().length); + + assertTrue(qc.getBits()[10] instanceof Type4); + assertTrue(qc.getBits()[11] instanceof Type4); + assertTrue(qc.getBits()[13] instanceof Type0); + assertTrue(qc.getBits()[14] instanceof Type12); + assertTrue(qc.getBits()[15] instanceof Type12); + assertTrue(qc.getBits()[16] instanceof Type8); + + Type4 plc10 = (Type4)qc.getBits()[10]; + Type4 plc11 = (Type4)qc.getBits()[11]; + Type0 plc13 = (Type0)qc.getBits()[13]; + Type12 plc14 = (Type12)qc.getBits()[14]; + Type12 plc15 = (Type12)qc.getBits()[15]; + Type8 plc16 = (Type8)qc.getBits()[16]; + + + assertEquals(1, plc10.getNumberOfPLCs()); + assertEquals(4, plc10.getPreData().length); + assertEquals(1, plc10.getPlcValA().length); + assertEquals(1, plc10.getPlcValB().length); + + assertEquals(0, plc10.getPreData()[0]); + assertEquals(0, plc10.getPreData()[1]); + assertEquals(0, plc10.getPreData()[2]); + assertEquals(0, plc10.getPreData()[3]); + assertEquals(0x5d0, plc10.getPlcValA()[0]); + assertEquals(0x800, plc10.getPlcValB()[0]); + + + assertEquals(2, plc11.getNumberOfPLCs()); + assertEquals(4, plc11.getPreData().length); + assertEquals(2, plc11.getPlcValA().length); + assertEquals(2, plc11.getPlcValB().length); + + assertEquals(0, plc11.getPreData()[0]); + assertEquals(0, plc11.getPreData()[1]); + assertEquals(0, plc11.getPreData()[2]); + assertEquals(0, plc11.getPreData()[3]); + assertEquals(0x53a, plc11.getPlcValA()[0]); + assertEquals(0x5d0, plc11.getPlcValB()[0]); + assertEquals(0xa00, plc11.getPlcValA()[1]); + assertEquals(0xc00, plc11.getPlcValB()[1]); + + + assertEquals(5, plc13.getNumberOfPLCs()); + assertEquals(4, plc13.getPreData().length); + assertEquals(5, plc13.getPlcValA().length); + assertEquals(5, plc13.getPlcValB().length); + + assertEquals(0xff00, plc13.getPreData()[0]); + assertEquals(0, plc13.getPreData()[1]); + assertEquals(0xf, plc13.getPreData()[2]); + assertEquals(0, plc13.getPreData()[3]); + assertEquals(0x19, plc13.getPlcValA()[0]); + assertEquals(0x00, plc13.getPlcValB()[0]); + assertEquals(0x27, plc13.getPlcValA()[1]); + assertEquals(0x00, plc13.getPlcValB()[1]); + assertEquals(0x36, plc13.getPlcValA()[2]); + assertEquals(0x00, plc13.getPlcValB()[2]); + assertEquals(0x42, plc13.getPlcValA()[3]); + assertEquals(0x00, plc13.getPlcValB()[3]); + assertEquals(0x50, plc13.getPlcValA()[4]); + assertEquals(0x00, plc13.getPlcValB()[4]); + + + // TODO - test the type 12s + + + assertEquals(6, plc16.getNumberOfPLCs()); + assertEquals(7, plc16.getPreData().length); + assertEquals(6, plc16.getPlcValA().length); + assertEquals(6, plc16.getPlcValB().length); + + assertEquals(0xff, plc16.getPreData()[0]); + assertEquals(0, plc16.getPreData()[1]); + assertEquals(0x56, plc16.getPreData()[2]); + assertEquals(0, plc16.getPreData()[3]); + assertEquals(0x62, plc16.getPreData()[4]); + assertEquals(0, plc16.getPreData()[5]); + assertEquals(0x3e, plc16.getPreData()[6]); + assertEquals(0x500000, plc16.getPlcValA()[0]); + assertEquals(0x570000, plc16.getPlcValB()[0]); + assertEquals(0x4b0000, plc16.getPlcValA()[1]); + assertEquals(0x000000, plc16.getPlcValB()[1]); + assertEquals(0x0a0000, plc16.getPlcValA()[2]); + assertEquals(0x22000000, plc16.getPlcValB()[2]); + assertEquals(0x000005, plc16.getPlcValA()[3]); + assertEquals(0x000004, plc16.getPlcValB()[3]); + assertEquals(0x000004, plc16.getPlcValA()[4]); + assertEquals(0x000004, plc16.getPlcValB()[4]); + assertEquals(0x000004, plc16.getPlcValA()[5]); + assertEquals(0x000004, plc16.getPlcValB()[5]); doc.close(); - } + } @Test - void testNoHyperlinks() throws IOException { - HPBFDocument doc = new HPBFDocument( + void testNoHyperlinks() throws IOException { + HPBFDocument doc = new HPBFDocument( _samples.openResourceAsStream("SampleNewsletter.pub") - ); + ); - QuillContents qc = doc.getQuillContents(); - assertEquals(20, qc.getBits().length); + QuillContents qc = doc.getQuillContents(); + assertEquals(20, qc.getBits().length); - Type12 plc18 = (Type12)qc.getBits()[18]; + Type12 plc18 = (Type12)qc.getBits()[18]; - assertEquals(1, plc18.getNumberOfPLCs()); - assertEquals(0, plc18.getNumberOfHyperlinks()); - assertEquals(0, plc18.getTextStartAt(0)); - assertEquals(601, plc18.getAllTextEndAt()); + assertEquals(1, plc18.getNumberOfPLCs()); + assertEquals(0, plc18.getNumberOfHyperlinks()); + assertEquals(0, plc18.getTextStartAt(0)); + assertEquals(601, plc18.getAllTextEndAt()); doc.close(); - } + } @Test - void testSimpleHyperlink() throws IOException { - HPBFDocument doc; - QuillContents qc; - Type12 hlBit; + void testSimpleHyperlink() throws IOException { + HPBFDocument doc; + QuillContents qc; + Type12 hlBit; - // Link at 10 - doc = new HPBFDocument( + // Link at 10 + doc = new HPBFDocument( _samples.openResourceAsStream("LinkAt10.pub") - ); - qc = doc.getQuillContents(); + ); + qc = doc.getQuillContents(); - hlBit = (Type12)qc.getBits()[12]; - assertEquals(1, hlBit.getNumberOfPLCs()); - assertEquals(1, hlBit.getNumberOfHyperlinks()); + hlBit = (Type12)qc.getBits()[12]; + assertEquals(1, hlBit.getNumberOfPLCs()); + assertEquals(1, hlBit.getNumberOfHyperlinks()); - assertEquals(10, hlBit.getTextStartAt(0)); - assertEquals(15, hlBit.getAllTextEndAt()); - assertEquals("http://poi.apache.org/", hlBit.getHyperlink(0)); + assertEquals(10, hlBit.getTextStartAt(0)); + assertEquals(15, hlBit.getAllTextEndAt()); + assertEquals("http://poi.apache.org/", hlBit.getHyperlink(0)); doc.close(); - // Longer link at 10 - doc = new HPBFDocument( + // Longer link at 10 + doc = new HPBFDocument( _samples.openResourceAsStream("LinkAt10Longer.pub") - ); - qc = doc.getQuillContents(); + ); + qc = doc.getQuillContents(); - hlBit = (Type12)qc.getBits()[12]; - assertEquals(1, hlBit.getNumberOfPLCs()); - assertEquals(1, hlBit.getNumberOfHyperlinks()); + hlBit = (Type12)qc.getBits()[12]; + assertEquals(1, hlBit.getNumberOfPLCs()); + assertEquals(1, hlBit.getNumberOfHyperlinks()); - assertEquals(10, hlBit.getTextStartAt(0)); - assertEquals(15, hlBit.getAllTextEndAt()); - assertEquals("http://poi.apache.org/hpbf/", hlBit.getHyperlink(0)); + assertEquals(10, hlBit.getTextStartAt(0)); + assertEquals(15, hlBit.getAllTextEndAt()); + assertEquals("http://poi.apache.org/hpbf/", hlBit.getHyperlink(0)); doc.close(); - // Link at 20 - doc = new HPBFDocument( + // Link at 20 + doc = new HPBFDocument( _samples.openResourceAsStream("LinkAt20.pub") - ); - qc = doc.getQuillContents(); + ); + qc = doc.getQuillContents(); - hlBit = (Type12)qc.getBits()[12]; - assertEquals(1, hlBit.getNumberOfPLCs()); - assertEquals(1, hlBit.getNumberOfHyperlinks()); + hlBit = (Type12)qc.getBits()[12]; + assertEquals(1, hlBit.getNumberOfPLCs()); + assertEquals(1, hlBit.getNumberOfHyperlinks()); - assertEquals(20, hlBit.getTextStartAt(0)); - assertEquals(25, hlBit.getAllTextEndAt()); - assertEquals("http://poi.apache.org/", hlBit.getHyperlink(0)); - doc.close(); - } + assertEquals(20, hlBit.getTextStartAt(0)); + assertEquals(25, hlBit.getAllTextEndAt()); + assertEquals("http://poi.apache.org/", hlBit.getHyperlink(0)); + doc.close(); + } @Test - void testManyHyperlinks() throws IOException { - HPBFDocument doc; - QuillContents qc; - Type12 hlBit; + void testManyHyperlinks() throws IOException { + HPBFDocument doc; + QuillContents qc; + Type12 hlBit; - // Link at 10 - doc = new HPBFDocument( + // Link at 10 + doc = new HPBFDocument( _samples.openResourceAsStream("LinkAt10.pub") - ); - qc = doc.getQuillContents(); + ); + qc = doc.getQuillContents(); - hlBit = (Type12)qc.getBits()[12]; - assertEquals(1, hlBit.getNumberOfPLCs()); - assertEquals(1, hlBit.getNumberOfHyperlinks()); + hlBit = (Type12)qc.getBits()[12]; + assertEquals(1, hlBit.getNumberOfPLCs()); + assertEquals(1, hlBit.getNumberOfHyperlinks()); - assertEquals(10, hlBit.getTextStartAt(0)); - assertEquals(15, hlBit.getAllTextEndAt()); - assertEquals("http://poi.apache.org/", hlBit.getHyperlink(0)); + assertEquals(10, hlBit.getTextStartAt(0)); + assertEquals(15, hlBit.getAllTextEndAt()); + assertEquals("http://poi.apache.org/", hlBit.getHyperlink(0)); doc.close(); - } + } @Test - void testHyperlinkDifferentVersions() throws IOException { - HPBFDocument doc; - QuillContents qc; - Type12 hlBitA; - Type12 hlBitB; - - // Latest version - doc = new HPBFDocument( + void testHyperlinkDifferentVersions() throws IOException { + HPBFDocument doc; + QuillContents qc; + Type12 hlBitA; + Type12 hlBitB; + + // Latest version + doc = new HPBFDocument( _samples.openResourceAsStream("Sample.pub") - ); - qc = doc.getQuillContents(); - - hlBitA = (Type12)qc.getBits()[14]; - assertEquals(2, hlBitA.getNumberOfPLCs()); - assertEquals(2, hlBitA.getNumberOfHyperlinks()); - - assertEquals(25, hlBitA.getTextStartAt(0)); - assertEquals(72, hlBitA.getTextStartAt(1)); - assertEquals(87, hlBitA.getAllTextEndAt()); - assertEquals("http://poi.apache.org/", hlBitA.getHyperlink(0)); - assertEquals("C:\\Documents and Settings\\Nick\\My Documents\\Booleans.xlsx", hlBitA.getHyperlink(1)); - - hlBitB = (Type12)qc.getBits()[15]; - assertEquals(3, hlBitB.getNumberOfPLCs()); - assertEquals(3, hlBitB.getNumberOfHyperlinks()); - - assertEquals(27, hlBitB.getTextStartAt(0)); - assertEquals(37, hlBitB.getTextStartAt(1)); - assertEquals(54, hlBitB.getTextStartAt(2)); - assertEquals(75, hlBitB.getAllTextEndAt()); - assertEquals("", hlBitB.getHyperlink(0)); - assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(1)); - assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(2)); + ); + qc = doc.getQuillContents(); + + hlBitA = (Type12)qc.getBits()[14]; + assertEquals(2, hlBitA.getNumberOfPLCs()); + assertEquals(2, hlBitA.getNumberOfHyperlinks()); + + assertEquals(25, hlBitA.getTextStartAt(0)); + assertEquals(72, hlBitA.getTextStartAt(1)); + assertEquals(87, hlBitA.getAllTextEndAt()); + assertEquals("http://poi.apache.org/", hlBitA.getHyperlink(0)); + assertEquals("C:\\Documents and Settings\\Nick\\My Documents\\Booleans.xlsx", hlBitA.getHyperlink(1)); + + hlBitB = (Type12)qc.getBits()[15]; + assertEquals(3, hlBitB.getNumberOfPLCs()); + assertEquals(3, hlBitB.getNumberOfHyperlinks()); + + assertEquals(27, hlBitB.getTextStartAt(0)); + assertEquals(37, hlBitB.getTextStartAt(1)); + assertEquals(54, hlBitB.getTextStartAt(2)); + assertEquals(75, hlBitB.getAllTextEndAt()); + assertEquals("", hlBitB.getHyperlink(0)); + assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(1)); + assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(2)); doc.close(); - // 2000 version - doc = new HPBFDocument( + // 2000 version + doc = new HPBFDocument( _samples.openResourceAsStream("Sample2000.pub") - ); - qc = doc.getQuillContents(); - - hlBitA = (Type12)qc.getBits()[13]; - assertEquals(2, hlBitA.getNumberOfPLCs()); - assertEquals(2, hlBitA.getNumberOfHyperlinks()); - - assertEquals(25, hlBitA.getTextStartAt(0)); - assertEquals(72, hlBitA.getTextStartAt(1)); - assertEquals(87, hlBitA.getAllTextEndAt()); - assertEquals("http://poi.apache.org/", hlBitA.getHyperlink(0)); - assertEquals("C:\\Documents and Settings\\Nick\\My Documents\\Booleans.xlsx", hlBitA.getHyperlink(1)); - - hlBitB = (Type12)qc.getBits()[14]; - assertEquals(3, hlBitB.getNumberOfPLCs()); - assertEquals(3, hlBitB.getNumberOfHyperlinks()); - - assertEquals(27, hlBitB.getTextStartAt(0)); - assertEquals(37, hlBitB.getTextStartAt(1)); - assertEquals(54, hlBitB.getTextStartAt(2)); - assertEquals(75, hlBitB.getAllTextEndAt()); - assertEquals("", hlBitB.getHyperlink(0)); - assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(1)); - assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(2)); + ); + qc = doc.getQuillContents(); + + hlBitA = (Type12)qc.getBits()[13]; + assertEquals(2, hlBitA.getNumberOfPLCs()); + assertEquals(2, hlBitA.getNumberOfHyperlinks()); + + assertEquals(25, hlBitA.getTextStartAt(0)); + assertEquals(72, hlBitA.getTextStartAt(1)); + assertEquals(87, hlBitA.getAllTextEndAt()); + assertEquals("http://poi.apache.org/", hlBitA.getHyperlink(0)); + assertEquals("C:\\Documents and Settings\\Nick\\My Documents\\Booleans.xlsx", hlBitA.getHyperlink(1)); + + hlBitB = (Type12)qc.getBits()[14]; + assertEquals(3, hlBitB.getNumberOfPLCs()); + assertEquals(3, hlBitB.getNumberOfHyperlinks()); + + assertEquals(27, hlBitB.getTextStartAt(0)); + assertEquals(37, hlBitB.getTextStartAt(1)); + assertEquals(54, hlBitB.getTextStartAt(2)); + assertEquals(75, hlBitB.getAllTextEndAt()); + assertEquals("", hlBitB.getHyperlink(0)); + assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(1)); + assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(2)); doc.close(); - // 98 version - doc = new HPBFDocument( + // 98 version + doc = new HPBFDocument( _samples.openResourceAsStream("Sample98.pub") - ); - qc = doc.getQuillContents(); - - hlBitA = (Type12)qc.getBits()[13]; - assertEquals(2, hlBitA.getNumberOfPLCs()); - assertEquals(2, hlBitA.getNumberOfHyperlinks()); - - assertEquals(25, hlBitA.getTextStartAt(0)); - assertEquals(72, hlBitA.getTextStartAt(1)); - assertEquals(87, hlBitA.getAllTextEndAt()); - assertEquals("http://poi.apache.org/", hlBitA.getHyperlink(0)); - assertEquals("C:\\Documents and Settings\\Nick\\My Documents\\Booleans.xlsx", hlBitA.getHyperlink(1)); - - hlBitB = (Type12)qc.getBits()[14]; - assertEquals(3, hlBitB.getNumberOfPLCs()); - assertEquals(3, hlBitB.getNumberOfHyperlinks()); - - assertEquals(27, hlBitB.getTextStartAt(0)); - assertEquals(37, hlBitB.getTextStartAt(1)); - assertEquals(54, hlBitB.getTextStartAt(2)); - assertEquals(75, hlBitB.getAllTextEndAt()); - assertEquals("", hlBitB.getHyperlink(0)); - assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(1)); - assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(2)); + ); + qc = doc.getQuillContents(); + + hlBitA = (Type12)qc.getBits()[13]; + assertEquals(2, hlBitA.getNumberOfPLCs()); + assertEquals(2, hlBitA.getNumberOfHyperlinks()); + + assertEquals(25, hlBitA.getTextStartAt(0)); + assertEquals(72, hlBitA.getTextStartAt(1)); + assertEquals(87, hlBitA.getAllTextEndAt()); + assertEquals("http://poi.apache.org/", hlBitA.getHyperlink(0)); + assertEquals("C:\\Documents and Settings\\Nick\\My Documents\\Booleans.xlsx", hlBitA.getHyperlink(1)); + + hlBitB = (Type12)qc.getBits()[14]; + assertEquals(3, hlBitB.getNumberOfPLCs()); + assertEquals(3, hlBitB.getNumberOfHyperlinks()); + + assertEquals(27, hlBitB.getTextStartAt(0)); + assertEquals(37, hlBitB.getTextStartAt(1)); + assertEquals(54, hlBitB.getTextStartAt(2)); + assertEquals(75, hlBitB.getAllTextEndAt()); + assertEquals("", hlBitB.getHyperlink(0)); + assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(1)); + assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(2)); doc.close(); } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/HSLFTestDataSamples.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/HSLFTestDataSamples.java index 9a08f18eb6..881d543b0d 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/HSLFTestDataSamples.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/HSLFTestDataSamples.java @@ -28,53 +28,53 @@ import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; public class HSLFTestDataSamples { - private static final POIDataSamples _inst = POIDataSamples.getSlideShowInstance(); + private static final POIDataSamples _inst = POIDataSamples.getSlideShowInstance(); - public static InputStream openSampleFileStream(String sampleFileName) { - return _inst.openResourceAsStream(sampleFileName); - } + public static InputStream openSampleFileStream(String sampleFileName) { + return _inst.openResourceAsStream(sampleFileName); + } - public static File getSampleFile(String sampleFileName) { - return _inst.getFile(sampleFileName); - } + public static File getSampleFile(String sampleFileName) { + return _inst.getFile(sampleFileName); + } - public static byte[] getTestDataFileContent(String fileName) { - return _inst.readFile(fileName); - } + public static byte[] getTestDataFileContent(String fileName) { + return _inst.readFile(fileName); + } - public static HSLFSlideShow getSlideShow(String fileName) throws IOException { + public static HSLFSlideShow getSlideShow(String fileName) throws IOException { try (InputStream is = openSampleFileStream(fileName)) { return new HSLFSlideShow(is); } - } + } - /** - * Writes a slideshow to a {@code UnsynchronizedByteArrayOutputStream} and reads it back - * from a {@code ByteArrayInputStream}.<p> - * Useful for verifying that the serialisation round trip - */ - public static HSLFSlideShowImpl writeOutAndReadBack(HSLFSlideShowImpl original) { - try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) { - original.write(baos); - try (InputStream is = baos.toInputStream()) { - return new HSLFSlideShowImpl(is); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } + /** + * Writes a slideshow to a {@code UnsynchronizedByteArrayOutputStream} and reads it back + * from a {@code ByteArrayInputStream}.<p> + * Useful for verifying that the serialisation round trip + */ + public static HSLFSlideShowImpl writeOutAndReadBack(HSLFSlideShowImpl original) { + try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) { + original.write(baos); + try (InputStream is = baos.toInputStream()) { + return new HSLFSlideShowImpl(is); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } - /** - * Writes a slideshow to a {@code UnsynchronizedByteArrayOutputStream} and reads it back - * from a {@code ByteArrayInputStream}.<p> - * Useful for verifying that the serialisation round trip - */ - public static HSLFSlideShow writeOutAndReadBack(HSLFSlideShow original) { - try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(4096)) { - original.write(baos); - return new HSLFSlideShow(baos.toInputStream()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + /** + * Writes a slideshow to a {@code UnsynchronizedByteArrayOutputStream} and reads it back + * from a {@code ByteArrayInputStream}.<p> + * Useful for verifying that the serialisation round trip + */ + public static HSLFSlideShow writeOutAndReadBack(HSLFSlideShow original) { + try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(4096)) { + original.write(baos); + return new HSLFSlideShow(baos.toInputStream()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestEncryptedFile.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestEncryptedFile.java index 64e61a4c14..5a2983027f 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestEncryptedFile.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestEncryptedFile.java @@ -36,16 +36,16 @@ public final class TestEncryptedFile { private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); @Test - void testLoadNonEncrypted() throws IOException { + void testLoadNonEncrypted() throws IOException { InputStream is = slTests.openResourceAsStream("basic_test_ppt_file.ppt"); - HSLFSlideShowImpl hss = new HSLFSlideShowImpl(is); - assertNotNull(hss); - hss.close(); - is.close(); - } + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(is); + assertNotNull(hss); + hss.close(); + is.close(); + } @Test - void testLoadEncrypted1() throws IOException { + void testLoadEncrypted1() throws IOException { try (InputStream is = slTests.openResourceAsStream("Password_Protected-hello.ppt")) { assertThrows(EncryptedPowerPointFileException.class, () -> new HSLFSlideShowImpl(is).close()); } @@ -63,5 +63,5 @@ public final class TestEncryptedFile { try (InputStream is = slTests.openResourceAsStream("Password_Protected-56-hello.ppt")) { assertThrows(EncryptedPowerPointFileException.class, () -> new HSLFSlideShowImpl(is).close()); } - } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestPOIDocumentScratchpad.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestPOIDocumentScratchpad.java index 2d795452b9..2d905db04e 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestPOIDocumentScratchpad.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestPOIDocumentScratchpad.java @@ -43,64 +43,64 @@ import org.junit.jupiter.api.Test; * which are part of the scratchpad (not main) */ public final class TestPOIDocumentScratchpad { - @Test - void testReadProperties() throws IOException { - try (POIDocument doc = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt")) { - testReadPropertiesHelper(doc); - } - } - - private void testReadPropertiesHelper(POIDocument docPH) { - // We should have both sets - assertNotNull(docPH.getDocumentSummaryInformation()); - assertNotNull(docPH.getSummaryInformation()); - - // Check they are as expected for the test doc - assertEquals("Hogwarts", docPH.getSummaryInformation().getAuthor()); - assertEquals(10598, docPH.getDocumentSummaryInformation().getByteCount()); - } - - @Test - void testReadProperties2() throws IOException { - try (POIDocument doc2 = HWPFTestDataSamples.openSampleFile("test2.doc")) { - // Check again on the word one - assertNotNull(doc2.getDocumentSummaryInformation()); - assertNotNull(doc2.getSummaryInformation()); - - assertEquals("Hogwarts", doc2.getSummaryInformation().getAuthor()); - assertEquals("", doc2.getSummaryInformation().getKeywords()); - assertEquals(0, doc2.getDocumentSummaryInformation().getByteCount()); - } - } - - @Test - void testWriteProperties() throws IOException { - // Just check we can write them back out into a filesystem - try (POIDocument doc = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); - POIFSFileSystem outFS = new POIFSFileSystem()) { - doc.writeProperties(outFS); - - // Should now hold them - assertNotNull(outFS.createDocumentInputStream(SummaryInformation.DEFAULT_STREAM_NAME)); - assertNotNull(outFS.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME)); - } - } - - @Test + @Test + void testReadProperties() throws IOException { + try (POIDocument doc = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt")) { + testReadPropertiesHelper(doc); + } + } + + private void testReadPropertiesHelper(POIDocument docPH) { + // We should have both sets + assertNotNull(docPH.getDocumentSummaryInformation()); + assertNotNull(docPH.getSummaryInformation()); + + // Check they are as expected for the test doc + assertEquals("Hogwarts", docPH.getSummaryInformation().getAuthor()); + assertEquals(10598, docPH.getDocumentSummaryInformation().getByteCount()); + } + + @Test + void testReadProperties2() throws IOException { + try (POIDocument doc2 = HWPFTestDataSamples.openSampleFile("test2.doc")) { + // Check again on the word one + assertNotNull(doc2.getDocumentSummaryInformation()); + assertNotNull(doc2.getSummaryInformation()); + + assertEquals("Hogwarts", doc2.getSummaryInformation().getAuthor()); + assertEquals("", doc2.getSummaryInformation().getKeywords()); + assertEquals(0, doc2.getDocumentSummaryInformation().getByteCount()); + } + } + + @Test + void testWriteProperties() throws IOException { + // Just check we can write them back out into a filesystem + try (POIDocument doc = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); + POIFSFileSystem outFS = new POIFSFileSystem()) { + doc.writeProperties(outFS); + + // Should now hold them + assertNotNull(outFS.createDocumentInputStream(SummaryInformation.DEFAULT_STREAM_NAME)); + assertNotNull(outFS.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME)); + } + } + + @Test void testWriteReadProperties() throws IOException { - // Write them out - try (POIDocument doc = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); - POIFSFileSystem outFS = new POIFSFileSystem()) { - doc.writeProperties(outFS); - - // Check they're still there - try (POIFSFileSystem inFS = writeOutAndReadBack(outFS); - POIDocument ppt = new HPSFPropertiesOnlyDocument(inFS)) { - ppt.readProperties(); - - // Delegate test - testReadPropertiesHelper(ppt); - } - } + // Write them out + try (POIDocument doc = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); + POIFSFileSystem outFS = new POIFSFileSystem()) { + doc.writeProperties(outFS); + + // Check they're still there + try (POIFSFileSystem inFS = writeOutAndReadBack(outFS); + POIDocument ppt = new HPSFPropertiesOnlyDocument(inFS)) { + ppt.readProperties(); + + // Delegate test + testReadPropertiesHelper(ppt); + } + } } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestRecordCounts.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestRecordCounts.java index 5c8463ca3e..b21f6ecc17 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestRecordCounts.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestRecordCounts.java @@ -35,58 +35,58 @@ import org.junit.jupiter.api.Test; */ public final class TestRecordCounts { - private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - // HSLFSlideShow primed on the test data - private HSLFSlideShowImpl ss; + private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); + // HSLFSlideShow primed on the test data + private HSLFSlideShowImpl ss; - @BeforeEach - void setup() throws Exception { - ss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - } + @BeforeEach + void setup() throws Exception { + ss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + } - @Test - void testSheetsCount() { - // Top level - Record[] r = ss.getRecords(); + @Test + void testSheetsCount() { + // Top level + Record[] r = ss.getRecords(); - int count = 0; - for (final Record rec : r) { - if(rec instanceof Slide) { - count++; - } - } - // Currently still sees the Master Sheet, but might not in the future - assertEquals(3,count); - } + int count = 0; + for (final Record rec : r) { + if(rec instanceof Slide) { + count++; + } + } + // Currently still sees the Master Sheet, but might not in the future + assertEquals(3,count); + } - @Test - void testNotesCount() { - // Top level - Record[] r = ss.getRecords(); + @Test + void testNotesCount() { + // Top level + Record[] r = ss.getRecords(); - int count = 0; - for (final Record rec : r) { - if (rec instanceof Notes && rec.getRecordType() == 1008L) { - count++; - } - } - // Two real sheets, plus the master sheet - assertEquals(3,count); - } + int count = 0; + for (final Record rec : r) { + if (rec instanceof Notes && rec.getRecordType() == 1008L) { + count++; + } + } + // Two real sheets, plus the master sheet + assertEquals(3,count); + } - @Test - void testSlideListWithTextCount() { - // Second level - Record[] rt = ss.getRecords(); - Record[] r = rt[0].getChildRecords(); + @Test + void testSlideListWithTextCount() { + // Second level + Record[] rt = ss.getRecords(); + Record[] r = rt[0].getChildRecords(); - int count = 0; - for (final Record rec : r) { - if (rec instanceof SlideListWithText && rec.getRecordType() == 4080L) { - count++; - } - } - // Two real sheets, plus the master sheet - assertEquals(3,count); - } + int count = 0; + for (final Record rec : r) { + if (rec instanceof SlideListWithText && rec.getRecordType() == 4080L) { + count++; + } + } + // Two real sheets, plus the master sheet + assertEquals(3,count); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java index ca5b1ac380..9797cb74c8 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java @@ -42,7 +42,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -@Isolated // this test changes global static BYTE_ARRAY_MAX_OVERRIDE +@Isolated // this test changes global static BYTE_ARRAY_MAX_OVERRIDE public abstract class BaseTestPPTIterating { protected static final Set<String> OLD_FILES = new HashSet<>(); static { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideShowDumper.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideShowDumper.java index 5eecf4370f..1b62833aec 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideShowDumper.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/TestSlideShowDumper.java @@ -31,7 +31,7 @@ import org.apache.poi.util.IOUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.Isolated; -@Isolated // this test changes global static BYTE_ARRAY_MAX_OVERRIDE +@Isolated // this test changes global static BYTE_ARRAY_MAX_OVERRIDE public class TestSlideShowDumper extends BaseTestPPTIterating { private static final Set<String> FAILING = new HashSet<>(); static { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/extractor/TestCruddyExtractor.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/extractor/TestCruddyExtractor.java index 71e1258d1e..e56aad9a17 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/extractor/TestCruddyExtractor.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/extractor/TestCruddyExtractor.java @@ -31,64 +31,64 @@ import org.junit.jupiter.api.Test; * Tests that the QuickButCruddyTextExtractor works correctly */ public final class TestCruddyExtractor { - private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - - // Extractor primed on the test data - private QuickButCruddyTextExtractor te; - - // All the text to be found in the file - String[] allTheText = new String[] { - "This is a test title", - "This is a test subtitle\nThis is on page 1", - "Click to edit Master title style", - "Click to edit Master text styles\nSecond level\nThird level\nFourth level\nFifth level", - "*", - "*", - "*", - "*", - "*", - "Click to edit Master text styles\nSecond level\nThird level\nFourth level\nFifth level", - "*", - "*", - "These are the notes for page 1", - "This is a test title", - "This is a test subtitle\nThis is on page 1", - "This is the title on page 2", - "This is page two\nIt has several blocks of text\nNone of them have formattingT", - "These are the notes on page two, again lacking formatting", - "This is a test title", - "This is a test subtitle\nThis is on page 1", - "This is the title on page 2", - "This is page two\nIt has several blocks of text\nNone of them have formatting", - }; - - @BeforeEach + private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); + + // Extractor primed on the test data + private QuickButCruddyTextExtractor te; + + // All the text to be found in the file + String[] allTheText = new String[] { + "This is a test title", + "This is a test subtitle\nThis is on page 1", + "Click to edit Master title style", + "Click to edit Master text styles\nSecond level\nThird level\nFourth level\nFifth level", + "*", + "*", + "*", + "*", + "*", + "Click to edit Master text styles\nSecond level\nThird level\nFourth level\nFifth level", + "*", + "*", + "These are the notes for page 1", + "This is a test title", + "This is a test subtitle\nThis is on page 1", + "This is the title on page 2", + "This is page two\nIt has several blocks of text\nNone of them have formattingT", + "These are the notes on page two, again lacking formatting", + "This is a test title", + "This is a test subtitle\nThis is on page 1", + "This is the title on page 2", + "This is page two\nIt has several blocks of text\nNone of them have formatting", + }; + + @BeforeEach void setup() throws Exception { - te = new QuickButCruddyTextExtractor(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + te = new QuickButCruddyTextExtractor(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); } - @Test + @Test void testReadAsVector() { - // Extract the text from the file as a vector - List<String> foundTextV = te.getTextAsVector(); - - // Ensure they match - assertEquals(allTheText.length,foundTextV.size()); - for(int i=0; i<allTheText.length; i++) { - String foundText = foundTextV.get(i); - assertEquals(allTheText[i],foundText); - } - } - - @Test - void testReadAsString() { - // Extract the text as a String - String foundText = te.getTextAsString(); - - // Turn the string array into a single string - String expectText = StringUtil.join(allTheText, "\n") + "\n"; - - // Ensure they match - assertEquals(expectText,foundText); - } + // Extract the text from the file as a vector + List<String> foundTextV = te.getTextAsVector(); + + // Ensure they match + assertEquals(allTheText.length,foundTextV.size()); + for(int i=0; i<allTheText.length; i++) { + String foundText = foundTextV.get(i); + assertEquals(allTheText[i],foundText); + } + } + + @Test + void testReadAsString() { + // Extract the text as a String + String foundText = te.getTextAsString(); + + // Turn the string array into a single string + String expectText = StringUtil.join(allTheText, "\n") + "\n"; + + // Ensure they match + assertEquals(expectText,foundText); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestOleEmbedding.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestOleEmbedding.java index dbab7b9fdc..1a443d1e18 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestOleEmbedding.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestOleEmbedding.java @@ -114,26 +114,26 @@ public final class TestOleEmbedding { @Test void testEmbedding() throws IOException { - HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - File pict = POIDataSamples.getSlideShowInstance().getFile("clock.jpg"); - HSLFPictureData pictData = ppt.addPicture(pict, PictureType.JPEG); + File pict = POIDataSamples.getSlideShowInstance().getFile("clock.jpg"); + HSLFPictureData pictData = ppt.addPicture(pict, PictureType.JPEG); - InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("Employee.xls"); - POIFSFileSystem poiData1 = new POIFSFileSystem(is); - is.close(); + InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("Employee.xls"); + POIFSFileSystem poiData1 = new POIFSFileSystem(is); + is.close(); - int oleObjectId1 = ppt.addEmbed(poiData1); + int oleObjectId1 = ppt.addEmbed(poiData1); - HSLFSlide slide1 = ppt.createSlide(); - HSLFObjectShape oleShape1 = new HSLFObjectShape(pictData); - oleShape1.setObjectID(oleObjectId1); - slide1.addShape(oleShape1); - oleShape1.setAnchor(new Rectangle2D.Double(100,100,100,100)); + HSLFSlide slide1 = ppt.createSlide(); + HSLFObjectShape oleShape1 = new HSLFObjectShape(pictData); + oleShape1.setObjectID(oleObjectId1); + slide1.addShape(oleShape1); + oleShape1.setAnchor(new Rectangle2D.Double(100,100,100,100)); - // add second slide with different order in object creation - HSLFSlide slide2 = ppt.createSlide(); - HSLFObjectShape oleShape2 = new HSLFObjectShape(pictData); + // add second slide with different order in object creation + HSLFSlide slide2 = ppt.createSlide(); + HSLFObjectShape oleShape2 = new HSLFObjectShape(pictData); is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleWithImages.xls"); POIFSFileSystem poiData2 = new POIFSFileSystem(is); @@ -145,22 +145,22 @@ public final class TestOleEmbedding { slide2.addShape(oleShape2); oleShape2.setAnchor(new Rectangle2D.Double(100,100,100,100)); - UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream(); - ppt.write(bos); + UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream(); + ppt.write(bos); - ppt = new HSLFSlideShow(bos.toInputStream()); - HSLFObjectShape comp = (HSLFObjectShape)ppt.getSlides().get(0).getShapes().get(0); + ppt = new HSLFSlideShow(bos.toInputStream()); + HSLFObjectShape comp = (HSLFObjectShape)ppt.getSlides().get(0).getShapes().get(0); byte[] compData = IOUtils.toByteArray(comp.getObjectData().getInputStream()); - bos.reset(); - poiData1.writeFilesystem(bos); + bos.reset(); + poiData1.writeFilesystem(bos); byte[] expData = bos.toByteArray(); - assertArrayEquals(expData, compData); + assertArrayEquals(expData, compData); - poiData1.close(); - poiData2.close(); - ppt.close(); + poiData1.close(); + poiData2.close(); + ppt.close(); } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestSlideChangeNotes.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestSlideChangeNotes.java index 6d8aaaac6a..8d3a1036a4 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestSlideChangeNotes.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestSlideChangeNotes.java @@ -30,34 +30,34 @@ import org.junit.jupiter.api.Test; * Tests that changing a slide's idea of what notes sheet is its works right */ public final class TestSlideChangeNotes { - // SlideShow primed on the test data - private HSLFSlideShow ss; + // SlideShow primed on the test data + private HSLFSlideShow ss; - @BeforeEach - void init() throws Exception { + @BeforeEach + void init() throws Exception { POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShowImpl hss = new HSLFSlideShowImpl(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new HSLFSlideShow(hss); - } + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); + } - @Test - void testSetToNone() { - HSLFSlide slideOne = ss.getSlides().get(0); - SlideAtom sa = slideOne.getSlideRecord().getSlideAtom(); + @Test + void testSetToNone() { + HSLFSlide slideOne = ss.getSlides().get(0); + SlideAtom sa = slideOne.getSlideRecord().getSlideAtom(); - slideOne.setNotes(null); + slideOne.setNotes(null); - assertEquals(0, sa.getNotesID()); - } + assertEquals(0, sa.getNotesID()); + } - @Test - void testSetToSomething() { - HSLFSlide slideOne = ss.getSlides().get(0); - HSLFNotes notesOne = ss.getNotes().get(1); - SlideAtom sa = slideOne.getSlideRecord().getSlideAtom(); + @Test + void testSetToSomething() { + HSLFSlide slideOne = ss.getSlides().get(0); + HSLFNotes notesOne = ss.getNotes().get(1); + SlideAtom sa = slideOne.getSlideRecord().getSlideAtom(); - slideOne.setNotes(notesOne); + slideOne.setNotes(notesOne); - assertEquals(notesOne._getSheetNumber(), sa.getNotesID()); - } + assertEquals(notesOne._getSheetNumber(), sa.getNotesID()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestTextRunReWrite.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestTextRunReWrite.java index 9509ca6c94..b38ae3ba51 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestTextRunReWrite.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestTextRunReWrite.java @@ -40,110 +40,110 @@ import org.junit.jupiter.api.Test; */ public final class TestTextRunReWrite { @Test - void testWritesOutTheSameNonRich() throws IOException { - try (HSLFSlideShow ppt1 = getSlideShow("Single_Coloured_Page_With_Fonts_and_Alignments.ppt")) { - // Ensure the text lengths are as we'd expect to start with - assertEquals(1, ppt1.getSlides().size()); - assertEquals(2, ppt1.getSlides().get(0).getTextParagraphs().size()); - - // Grab the first text run on the first sheet - List<HSLFTextParagraph> tr1 = ppt1.getSlides().get(0).getTextParagraphs().get(0); - List<HSLFTextParagraph> tr2 = ppt1.getSlides().get(0).getTextParagraphs().get(1); - - - assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); - assertEquals(179, HSLFTextParagraph.getRawText(tr2).length()); - - assertEquals(1, tr1.size()); - assertEquals(30, HSLFTextParagraph.getText(tr1).length()); - assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); - assertEquals(31, tr1.get(0).getTextRuns().get(0).getCharacterStyle().getCharactersCovered()); - assertEquals(31, tr1.get(0).getParagraphStyle().getCharactersCovered()); - - // Set the text to be as it is now - HSLFTextParagraph.setText(tr1, HSLFTextParagraph.getRawText(tr1)); - tr1 = ppt1.getSlides().get(0).getTextParagraphs().get(0); - - // Check the text lengths are still right - assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); - assertEquals(179, HSLFTextParagraph.getRawText(tr2).length()); - - assertEquals(1, tr1.size()); - assertEquals(30, HSLFTextParagraph.getText(tr1).length()); - assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); - assertEquals(31, tr1.get(0).getTextRuns().get(0).getCharacterStyle().getCharactersCovered()); - assertEquals(31, tr1.get(0).getParagraphStyle().getCharactersCovered()); - - // Use POIFS to query that lot - try (POIFSFileSystem npfs = writeOutAndReadBack(ppt1.getDirectory().getFileSystem())) { - // Check that the "PowerPoint Document" sections have the same size - DirectoryNode oDir = ppt1.getSlideShowImpl().getDirectory(); - - DocumentEntry oProps = (DocumentEntry) oDir.getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); - DocumentEntry nProps = (DocumentEntry) npfs.getRoot().getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); - assertEquals(oProps.getSize(), nProps.getSize()); - - // Check that they contain the same data - byte[] _oData = new byte[oProps.getSize()]; - byte[] _nData = new byte[nProps.getSize()]; - int oLen = oDir.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT).read(_oData); - int nLen = npfs.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT).read(_nData); - assertEquals(_oData.length, oLen); - assertEquals(_nData.length, nLen); - assertArrayEquals(_oData, _nData); - } - } - } + void testWritesOutTheSameNonRich() throws IOException { + try (HSLFSlideShow ppt1 = getSlideShow("Single_Coloured_Page_With_Fonts_and_Alignments.ppt")) { + // Ensure the text lengths are as we'd expect to start with + assertEquals(1, ppt1.getSlides().size()); + assertEquals(2, ppt1.getSlides().get(0).getTextParagraphs().size()); + + // Grab the first text run on the first sheet + List<HSLFTextParagraph> tr1 = ppt1.getSlides().get(0).getTextParagraphs().get(0); + List<HSLFTextParagraph> tr2 = ppt1.getSlides().get(0).getTextParagraphs().get(1); + + + assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); + assertEquals(179, HSLFTextParagraph.getRawText(tr2).length()); + + assertEquals(1, tr1.size()); + assertEquals(30, HSLFTextParagraph.getText(tr1).length()); + assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); + assertEquals(31, tr1.get(0).getTextRuns().get(0).getCharacterStyle().getCharactersCovered()); + assertEquals(31, tr1.get(0).getParagraphStyle().getCharactersCovered()); + + // Set the text to be as it is now + HSLFTextParagraph.setText(tr1, HSLFTextParagraph.getRawText(tr1)); + tr1 = ppt1.getSlides().get(0).getTextParagraphs().get(0); + + // Check the text lengths are still right + assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); + assertEquals(179, HSLFTextParagraph.getRawText(tr2).length()); + + assertEquals(1, tr1.size()); + assertEquals(30, HSLFTextParagraph.getText(tr1).length()); + assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); + assertEquals(31, tr1.get(0).getTextRuns().get(0).getCharacterStyle().getCharactersCovered()); + assertEquals(31, tr1.get(0).getParagraphStyle().getCharactersCovered()); + + // Use POIFS to query that lot + try (POIFSFileSystem npfs = writeOutAndReadBack(ppt1.getDirectory().getFileSystem())) { + // Check that the "PowerPoint Document" sections have the same size + DirectoryNode oDir = ppt1.getSlideShowImpl().getDirectory(); + + DocumentEntry oProps = (DocumentEntry) oDir.getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); + DocumentEntry nProps = (DocumentEntry) npfs.getRoot().getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); + assertEquals(oProps.getSize(), nProps.getSize()); + + // Check that they contain the same data + byte[] _oData = new byte[oProps.getSize()]; + byte[] _nData = new byte[nProps.getSize()]; + int oLen = oDir.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT).read(_oData); + int nLen = npfs.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT).read(_nData); + assertEquals(_oData.length, oLen); + assertEquals(_nData.length, nLen); + assertArrayEquals(_oData, _nData); + } + } + } @Test void testWritesOutTheSameRich() throws IOException { - try (HSLFSlideShow ppt1 = getSlideShow("Single_Coloured_Page_With_Fonts_and_Alignments.ppt")) { - // Grab the first text run on the first sheet - List<HSLFTextParagraph> tr1 = ppt1.getSlides().get(0).getTextParagraphs().get(0); - - // Get the first rich text run - HSLFTextRun rtr1 = tr1.get(0).getTextRuns().get(0); - - // Check that the text sizes are as expected - assertEquals(1, tr1.get(0).getTextRuns().size()); - assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); - assertEquals(30, rtr1.getLength()); - assertEquals(30, rtr1.getRawText().length()); - assertEquals(31, rtr1.getCharacterStyle().getCharactersCovered()); - assertEquals(31, tr1.get(0).getParagraphStyle().getCharactersCovered()); - - // Set the text to be as it is now - rtr1.setText(rtr1.getRawText()); - rtr1 = tr1.get(0).getTextRuns().get(0); - - // Check that the text sizes are still as expected - assertEquals(1, tr1.get(0).getTextRuns().size()); - assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); - assertEquals(30, tr1.get(0).getTextRuns().get(0).getRawText().length()); - assertEquals(30, rtr1.getLength()); - assertEquals(30, rtr1.getRawText().length()); - assertEquals(31, rtr1.getCharacterStyle().getCharactersCovered()); - assertEquals(31, tr1.get(0).getParagraphStyle().getCharactersCovered()); - - // Use POIFS to query that lot - try (POIFSFileSystem npfs = writeOutAndReadBack(ppt1.getDirectory().getFileSystem())) { - // Check that the "PowerPoint Document" sections have the same size - DirectoryNode oDir = ppt1.getSlideShowImpl().getDirectory(); - - DocumentEntry oProps = (DocumentEntry) oDir.getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); - DocumentEntry nProps = (DocumentEntry) npfs.getRoot().getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); - assertEquals(oProps.getSize(), nProps.getSize()); - - // Check that they contain the same data - byte[] _oData = new byte[oProps.getSize()]; - byte[] _nData = new byte[nProps.getSize()]; - - int oLen = oDir.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT).read(_oData); - int nLen = npfs.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT).read(_nData); - assertEquals(_oData.length, oLen); - assertEquals(_nData.length, nLen); - assertArrayEquals(_oData, _nData); - } - } - } + try (HSLFSlideShow ppt1 = getSlideShow("Single_Coloured_Page_With_Fonts_and_Alignments.ppt")) { + // Grab the first text run on the first sheet + List<HSLFTextParagraph> tr1 = ppt1.getSlides().get(0).getTextParagraphs().get(0); + + // Get the first rich text run + HSLFTextRun rtr1 = tr1.get(0).getTextRuns().get(0); + + // Check that the text sizes are as expected + assertEquals(1, tr1.get(0).getTextRuns().size()); + assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); + assertEquals(30, rtr1.getLength()); + assertEquals(30, rtr1.getRawText().length()); + assertEquals(31, rtr1.getCharacterStyle().getCharactersCovered()); + assertEquals(31, tr1.get(0).getParagraphStyle().getCharactersCovered()); + + // Set the text to be as it is now + rtr1.setText(rtr1.getRawText()); + rtr1 = tr1.get(0).getTextRuns().get(0); + + // Check that the text sizes are still as expected + assertEquals(1, tr1.get(0).getTextRuns().size()); + assertEquals(30, HSLFTextParagraph.getRawText(tr1).length()); + assertEquals(30, tr1.get(0).getTextRuns().get(0).getRawText().length()); + assertEquals(30, rtr1.getLength()); + assertEquals(30, rtr1.getRawText().length()); + assertEquals(31, rtr1.getCharacterStyle().getCharactersCovered()); + assertEquals(31, tr1.get(0).getParagraphStyle().getCharactersCovered()); + + // Use POIFS to query that lot + try (POIFSFileSystem npfs = writeOutAndReadBack(ppt1.getDirectory().getFileSystem())) { + // Check that the "PowerPoint Document" sections have the same size + DirectoryNode oDir = ppt1.getSlideShowImpl().getDirectory(); + + DocumentEntry oProps = (DocumentEntry) oDir.getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); + DocumentEntry nProps = (DocumentEntry) npfs.getRoot().getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); + assertEquals(oProps.getSize(), nProps.getSize()); + + // Check that they contain the same data + byte[] _oData = new byte[oProps.getSize()]; + byte[] _nData = new byte[nProps.getSize()]; + + int oLen = oDir.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT).read(_oData); + int nLen = npfs.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT).read(_nData); + assertEquals(_oData.length, oLen); + assertEquals(_nData.length, nLen); + assertArrayEquals(_oData, _nData); + } + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCString.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCString.java index 054b5c9790..57af6afcb5 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCString.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCString.java @@ -29,79 +29,79 @@ import org.junit.jupiter.api.Test; * Tests that CString works properly */ public final class TestCString { - // From a real file - private final byte[] data_a = { 0, 0, 0xBA-256, 0x0f, 0x10, 0, 0, 0, - 0x48, 0, 0x6F, 0, 0x67, 0, 0x77, 0, - 0x61, 0, 0x72, 0, 0x74, 0, 0x73, 0 }; - private final byte[] data_b = new byte[] { 0x10, 0, 0xBA-256, 0x0f, 0x10, 0, 0, 0, - 0x43, 0, 0x6F, 0, 0x6D, 0, 0x6D, 0, - 0x65, 0, 0x6E, 0, 0x74, 0, 0x73, 0 }; - - @Test + // From a real file + private final byte[] data_a = { 0, 0, 0xBA-256, 0x0f, 0x10, 0, 0, 0, + 0x48, 0, 0x6F, 0, 0x67, 0, 0x77, 0, + 0x61, 0, 0x72, 0, 0x74, 0, 0x73, 0 }; + private final byte[] data_b = new byte[] { 0x10, 0, 0xBA-256, 0x0f, 0x10, 0, 0, 0, + 0x43, 0, 0x6F, 0, 0x6D, 0, 0x6D, 0, + 0x65, 0, 0x6E, 0, 0x74, 0, 0x73, 0 }; + + @Test void testRecordType() { - CString ca = new CString(data_a, 0, data_a.length); - assertEquals(4026L, ca.getRecordType()); - CString cb = new CString(data_b, 0, data_a.length); - assertEquals(4026L, cb.getRecordType()); - } - - @Test - void testCount() { - CString ca = new CString(data_a, 0, data_a.length); - assertEquals(0, ca.getOptions()); - CString cb = new CString(data_b, 0, data_a.length); - assertEquals(0x10, cb.getOptions()); - - ca.setOptions(28); - assertEquals(28, ca.getOptions()); - } - - @Test - void testText() { - CString ca = new CString(data_a, 0, data_a.length); - assertEquals("Hogwarts", ca.getText()); - CString cb = new CString(data_b, 0, data_a.length); - assertEquals("Comments", cb.getText()); - - ca.setText("FooBar"); - assertEquals("FooBar", ca.getText()); - } - - @Test - void testWrite() throws Exception { - CString ca = new CString(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ca.writeOut(baos); - byte[] b = baos.toByteArray(); - assertArrayEquals(data_a, b); - - CString cb = new CString(data_b, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baosB = new UnsynchronizedByteArrayOutputStream(); - cb.writeOut(baosB); - b = baosB.toByteArray(); - assertArrayEquals(data_b, b); - } - - // Turn data_a into data_b - @Test - void testChange() throws Exception { - CString ca = new CString(data_a, 0, data_a.length); - ca.setText("Comments"); - ca.setOptions(0x10); - - // Check bytes weren't the same - boolean equals = true; - for(int i=0; i<data_a.length; i++) { - if (data_a[i] != data_b[i]) { - equals = false; - break; - } - } - assertFalse(equals, "Arrays should not be equals"); - - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ca.writeOut(baos); - byte[] b = baos.toByteArray(); - assertArrayEquals(data_b, b); - } + CString ca = new CString(data_a, 0, data_a.length); + assertEquals(4026L, ca.getRecordType()); + CString cb = new CString(data_b, 0, data_a.length); + assertEquals(4026L, cb.getRecordType()); + } + + @Test + void testCount() { + CString ca = new CString(data_a, 0, data_a.length); + assertEquals(0, ca.getOptions()); + CString cb = new CString(data_b, 0, data_a.length); + assertEquals(0x10, cb.getOptions()); + + ca.setOptions(28); + assertEquals(28, ca.getOptions()); + } + + @Test + void testText() { + CString ca = new CString(data_a, 0, data_a.length); + assertEquals("Hogwarts", ca.getText()); + CString cb = new CString(data_b, 0, data_a.length); + assertEquals("Comments", cb.getText()); + + ca.setText("FooBar"); + assertEquals("FooBar", ca.getText()); + } + + @Test + void testWrite() throws Exception { + CString ca = new CString(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ca.writeOut(baos); + byte[] b = baos.toByteArray(); + assertArrayEquals(data_a, b); + + CString cb = new CString(data_b, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baosB = new UnsynchronizedByteArrayOutputStream(); + cb.writeOut(baosB); + b = baosB.toByteArray(); + assertArrayEquals(data_b, b); + } + + // Turn data_a into data_b + @Test + void testChange() throws Exception { + CString ca = new CString(data_a, 0, data_a.length); + ca.setText("Comments"); + ca.setOptions(0x10); + + // Check bytes weren't the same + boolean equals = true; + for(int i=0; i<data_a.length; i++) { + if (data_a[i] != data_b[i]) { + equals = false; + break; + } + } + assertFalse(equals, "Arrays should not be equals"); + + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ca.writeOut(baos); + byte[] b = baos.toByteArray(); + assertArrayEquals(data_b, b); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestColorSchemeAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestColorSchemeAtom.java index fc74f17613..03d657a42f 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestColorSchemeAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestColorSchemeAtom.java @@ -28,63 +28,63 @@ import org.junit.jupiter.api.Test; * Tests that ColorSchemAtom works properly */ public final class TestColorSchemeAtom { - // From a real file - private final byte[] data_a = { 60, 0, 0xF0-256, 0x07, 0x20, 0, 0, 0, - 0xFF-256, 0xFF-256, 0xFF-256, 0, 0, 0, 0, 0, - 0x80-256, 0x80-256, 0x80-256, 0, 0, 0, 0, 0, - 0xBB-256, 0xE0-256, 0xE3-256, 0, 0x33, 0x33, 0x99-256, 0, - 0, 0x99-256, 0x99-256, 0, 0x99-256, 0xCC-256, 0, 0 - }; - - @Test - void testRecordType() { - ColorSchemeAtom csa = new ColorSchemeAtom(data_a,0,data_a.length); - assertEquals(2032L, csa.getRecordType()); - } - - @Test - void testToRGB() { - byte[] rgb = ColorSchemeAtom.splitRGB(3669760); - - assertEquals(3,rgb.length); - assertEquals(0, rgb[0]); - assertEquals(255-256, rgb[1]); - assertEquals(55, rgb[2]); - } - - @Test - void testFromRGB() { - byte[] rgb_a = new byte[] { 0, 255-256, 55 }; - byte[] rgb_b = new byte[] { 255-256, 127, 79 }; - - assertEquals( 3669760, ColorSchemeAtom.joinRGB( rgb_a ) ); - assertEquals( 5210111, ColorSchemeAtom.joinRGB( rgb_b ) ); - - assertEquals( 3669760, ColorSchemeAtom.joinRGB( rgb_a[0], rgb_a[1], rgb_a[2] ) ); - assertEquals( 5210111, ColorSchemeAtom.joinRGB( rgb_b[0], rgb_b[1], rgb_b[2] ) ); - } - - @Test - void testRGBs() { - ColorSchemeAtom csa = new ColorSchemeAtom(data_a,0,data_a.length); - - assertEquals( 16777215 , csa.getBackgroundColourRGB() ); - assertEquals( 0 , csa.getTextAndLinesColourRGB() ); - assertEquals( 8421504 , csa.getShadowsColourRGB() ); - assertEquals( 0 , csa.getTitleTextColourRGB() ); - assertEquals( 14934203 , csa.getFillsColourRGB() ); - assertEquals( 10040115 , csa.getAccentColourRGB() ); - assertEquals( 10066176 , csa.getAccentAndHyperlinkColourRGB() ); - assertEquals( 52377 , csa.getAccentAndFollowingHyperlinkColourRGB() ); - } - - @Test - void testWrite() throws Exception { - ColorSchemeAtom csa = new ColorSchemeAtom(data_a,0,data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - csa.writeOut(baos); - byte[] b = baos.toByteArray(); - - assertArrayEquals(data_a, b); - } + // From a real file + private final byte[] data_a = { 60, 0, 0xF0-256, 0x07, 0x20, 0, 0, 0, + 0xFF-256, 0xFF-256, 0xFF-256, 0, 0, 0, 0, 0, + 0x80-256, 0x80-256, 0x80-256, 0, 0, 0, 0, 0, + 0xBB-256, 0xE0-256, 0xE3-256, 0, 0x33, 0x33, 0x99-256, 0, + 0, 0x99-256, 0x99-256, 0, 0x99-256, 0xCC-256, 0, 0 + }; + + @Test + void testRecordType() { + ColorSchemeAtom csa = new ColorSchemeAtom(data_a,0,data_a.length); + assertEquals(2032L, csa.getRecordType()); + } + + @Test + void testToRGB() { + byte[] rgb = ColorSchemeAtom.splitRGB(3669760); + + assertEquals(3,rgb.length); + assertEquals(0, rgb[0]); + assertEquals(255-256, rgb[1]); + assertEquals(55, rgb[2]); + } + + @Test + void testFromRGB() { + byte[] rgb_a = new byte[] { 0, 255-256, 55 }; + byte[] rgb_b = new byte[] { 255-256, 127, 79 }; + + assertEquals( 3669760, ColorSchemeAtom.joinRGB( rgb_a ) ); + assertEquals( 5210111, ColorSchemeAtom.joinRGB( rgb_b ) ); + + assertEquals( 3669760, ColorSchemeAtom.joinRGB( rgb_a[0], rgb_a[1], rgb_a[2] ) ); + assertEquals( 5210111, ColorSchemeAtom.joinRGB( rgb_b[0], rgb_b[1], rgb_b[2] ) ); + } + + @Test + void testRGBs() { + ColorSchemeAtom csa = new ColorSchemeAtom(data_a,0,data_a.length); + + assertEquals( 16777215 , csa.getBackgroundColourRGB() ); + assertEquals( 0 , csa.getTextAndLinesColourRGB() ); + assertEquals( 8421504 , csa.getShadowsColourRGB() ); + assertEquals( 0 , csa.getTitleTextColourRGB() ); + assertEquals( 14934203 , csa.getFillsColourRGB() ); + assertEquals( 10040115 , csa.getAccentColourRGB() ); + assertEquals( 10066176 , csa.getAccentAndHyperlinkColourRGB() ); + assertEquals( 52377 , csa.getAccentAndFollowingHyperlinkColourRGB() ); + } + + @Test + void testWrite() throws Exception { + ColorSchemeAtom csa = new ColorSchemeAtom(data_a,0,data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + csa.writeOut(baos); + byte[] b = baos.toByteArray(); + + assertArrayEquals(data_a, b); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestComment2000.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestComment2000.java index ffff00f289..32213d0e4d 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestComment2000.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestComment2000.java @@ -38,182 +38,182 @@ import org.junit.jupiter.api.Test; * TODO: Test Comment200Atom within */ public final class TestComment2000 { - // From a real file - private final byte[] data_a = new byte[] { - 0x0F, 0, 0xE0-256, 0x2E, 0x9C-256, 0, 0, 0, - 0, 0, 0xBA-256, 0x0F, 0x14, 0, 0, 0, - 0x44, 0, 0x75, 0, 0x6D, 0, 0x62, 0, - 0x6C, 0, 0x65, 0, 0x64, 0, 0x6F, 0, - 0x72, 0, 0x65, 0, - 0x10, 0, 0xBA-256, 0x0F, 0x4A, 0, 0, 0, - 0x59, 0, 0x65, 0, 0x73, 0, 0x2C, 0, - 0x20, 0, 0x74, 0, 0x68, 0, 0x65, 0, - 0x79, 0, 0x20, 0, 0x63, 0, 0x65, 0, - 0x72, 0, 0x74, 0, 0x61, 0, 0x69, 0, - 0x6E, 0, 0x6C, 0, 0x79, 0, 0x20, 0, - 0x61, 0, 0x72, 0, 0x65, 0, 0x2C, 0, - 0x20, 0, 0x61, 0, 0x72, 0, 0x65, 0, - 0x6E, 0, 0x27, 0, 0x74, 0, 0x20, 0, - 0x74, 0, 0x68, 0, 0x65, 0, 0x79, 0, 0x21, 0, - 0x20, 0, 0xBA-256, 0x0F, 0x02, 0, 0, 0, - 0x44, 0, - 0, 0, 0xE1-256, 0x2E, 0x1C, 0, 0, 0, - 0x01, 0, 0, 0, 0xD6-256, 0x07, 0x01, 0, - 0x02, 0, 0x18, 0, 0x0A, 0, 0x1A, 0, - 0x0F, 0, 0xCD-256, 0, 0x92-256, 0, - 0, 0, 0x92-256, 0, 0, 0 - }; - private final byte[] data_b = new byte[] { - 0x0F, 0, 0xE0-256, 0x2E, 0xAC-256, 0, 0, 0, - 0, 0, 0xBA-256, 0x0F, 0x10, 0, 0, 0, - 0x48, 0, 0x6F, 0, 0x67, 0, 0x77, 0, - 0x61, 0, 0x72, 0, 0x74, 0, 0x73, 0, - 0x10, 0, 0xBA-256, 0x0F, 0x5E, 0, 0, 0, - 0x43, 0, 0x6F, 0, 0x6D, 0, 0x6D, 0, - 0x65, 0, 0x6E, 0, 0x74, 0, 0x73, 0, - 0x20, 0, 0x61, 0, 0x72, 0, 0x65, 0, - 0x20, 0, 0x66, 0, 0x75, 0, 0x6E, 0, - 0x20, 0, 0x74, 0, 0x68, 0, 0x69, 0, - 0x6E, 0, 0x67, 0, 0x73, 0, 0x20, 0, - 0x74, 0, 0x6F, 0, 0x20, 0, 0x61, 0, - 0x64, 0, 0x64, 0, 0x20, 0, 0x69, 0, - 0x6E, 0, 0x2C, 0, 0x20, 0, 0x61, 0, - 0x72, 0, 0x65, 0, 0x6E, 0, 0x27, 0, - 0x74, 0, 0x20, 0, 0x74, 0, 0x68, 0, - 0x65, 0, 0x79, 0, 0x3F, 0, - 0x20, 0, 0xBA-256, 0x0F, 0x02, 0, 0, 0, - 0x48, 0, - 0, 0, 0xE1-256, 0x2E, 0x1C, 0, 0, 0, - 0x01, 0, 0, 0, 0xD6-256, 0x07, 0x01, 0, - 0x02, 0, 0x18, 0, 0x16, 0, 0x19, 0, 0x03, - 0, 0xD5-256, 0x02, 0x0A, 0, 0, 0, - 0x0A, 0, 0, 0 - }; - - private static SimpleDateFormat sdf; - - @BeforeAll - public static void initDateFormat() { - sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ROOT); - sdf.setTimeZone(LocaleUtil.getUserTimeZone()); - } + // From a real file + private final byte[] data_a = new byte[] { + 0x0F, 0, 0xE0-256, 0x2E, 0x9C-256, 0, 0, 0, + 0, 0, 0xBA-256, 0x0F, 0x14, 0, 0, 0, + 0x44, 0, 0x75, 0, 0x6D, 0, 0x62, 0, + 0x6C, 0, 0x65, 0, 0x64, 0, 0x6F, 0, + 0x72, 0, 0x65, 0, + 0x10, 0, 0xBA-256, 0x0F, 0x4A, 0, 0, 0, + 0x59, 0, 0x65, 0, 0x73, 0, 0x2C, 0, + 0x20, 0, 0x74, 0, 0x68, 0, 0x65, 0, + 0x79, 0, 0x20, 0, 0x63, 0, 0x65, 0, + 0x72, 0, 0x74, 0, 0x61, 0, 0x69, 0, + 0x6E, 0, 0x6C, 0, 0x79, 0, 0x20, 0, + 0x61, 0, 0x72, 0, 0x65, 0, 0x2C, 0, + 0x20, 0, 0x61, 0, 0x72, 0, 0x65, 0, + 0x6E, 0, 0x27, 0, 0x74, 0, 0x20, 0, + 0x74, 0, 0x68, 0, 0x65, 0, 0x79, 0, 0x21, 0, + 0x20, 0, 0xBA-256, 0x0F, 0x02, 0, 0, 0, + 0x44, 0, + 0, 0, 0xE1-256, 0x2E, 0x1C, 0, 0, 0, + 0x01, 0, 0, 0, 0xD6-256, 0x07, 0x01, 0, + 0x02, 0, 0x18, 0, 0x0A, 0, 0x1A, 0, + 0x0F, 0, 0xCD-256, 0, 0x92-256, 0, + 0, 0, 0x92-256, 0, 0, 0 + }; + private final byte[] data_b = new byte[] { + 0x0F, 0, 0xE0-256, 0x2E, 0xAC-256, 0, 0, 0, + 0, 0, 0xBA-256, 0x0F, 0x10, 0, 0, 0, + 0x48, 0, 0x6F, 0, 0x67, 0, 0x77, 0, + 0x61, 0, 0x72, 0, 0x74, 0, 0x73, 0, + 0x10, 0, 0xBA-256, 0x0F, 0x5E, 0, 0, 0, + 0x43, 0, 0x6F, 0, 0x6D, 0, 0x6D, 0, + 0x65, 0, 0x6E, 0, 0x74, 0, 0x73, 0, + 0x20, 0, 0x61, 0, 0x72, 0, 0x65, 0, + 0x20, 0, 0x66, 0, 0x75, 0, 0x6E, 0, + 0x20, 0, 0x74, 0, 0x68, 0, 0x69, 0, + 0x6E, 0, 0x67, 0, 0x73, 0, 0x20, 0, + 0x74, 0, 0x6F, 0, 0x20, 0, 0x61, 0, + 0x64, 0, 0x64, 0, 0x20, 0, 0x69, 0, + 0x6E, 0, 0x2C, 0, 0x20, 0, 0x61, 0, + 0x72, 0, 0x65, 0, 0x6E, 0, 0x27, 0, + 0x74, 0, 0x20, 0, 0x74, 0, 0x68, 0, + 0x65, 0, 0x79, 0, 0x3F, 0, + 0x20, 0, 0xBA-256, 0x0F, 0x02, 0, 0, 0, + 0x48, 0, + 0, 0, 0xE1-256, 0x2E, 0x1C, 0, 0, 0, + 0x01, 0, 0, 0, 0xD6-256, 0x07, 0x01, 0, + 0x02, 0, 0x18, 0, 0x16, 0, 0x19, 0, 0x03, + 0, 0xD5-256, 0x02, 0x0A, 0, 0, 0, + 0x0A, 0, 0, 0 + }; + + private static SimpleDateFormat sdf; + + @BeforeAll + public static void initDateFormat() { + sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ROOT); + sdf.setTimeZone(LocaleUtil.getUserTimeZone()); + } @Test void testRecordType() { - Comment2000 ca = new Comment2000(data_a, 0, data_a.length); - assertEquals(12000L, ca.getRecordType()); - } + Comment2000 ca = new Comment2000(data_a, 0, data_a.length); + assertEquals(12000L, ca.getRecordType()); + } @Test void testAuthor() { - Comment2000 ca = new Comment2000(data_a, 0, data_a.length); - assertEquals("Dumbledore", ca.getAuthor()); - assertEquals("D", ca.getAuthorInitials()); - } + Comment2000 ca = new Comment2000(data_a, 0, data_a.length); + assertEquals("Dumbledore", ca.getAuthor()); + assertEquals("D", ca.getAuthorInitials()); + } @Test void testText() { - Comment2000 ca = new Comment2000(data_a, 0, data_a.length); - assertEquals("Yes, they certainly are, aren't they!", ca.getText()); - } + Comment2000 ca = new Comment2000(data_a, 0, data_a.length); + assertEquals("Yes, they certainly are, aren't they!", ca.getText()); + } @Test void testCommentAtom() throws Exception { - Comment2000 ca = new Comment2000(data_a, 0, data_a.length); - Comment2000Atom c2a = ca.getComment2000Atom(); - - assertEquals(1, c2a.getNumber()); - assertEquals(0x92, c2a.getXOffset()); - assertEquals(0x92, c2a.getYOffset()); - Date exp_a = sdf.parse("2006-01-24 10:26:15.205"); - assertEquals(exp_a, c2a.getDate()); - } + Comment2000 ca = new Comment2000(data_a, 0, data_a.length); + Comment2000Atom c2a = ca.getComment2000Atom(); + + assertEquals(1, c2a.getNumber()); + assertEquals(0x92, c2a.getXOffset()); + assertEquals(0x92, c2a.getYOffset()); + Date exp_a = sdf.parse("2006-01-24 10:26:15.205"); + assertEquals(exp_a, c2a.getDate()); + } @Test void testCommentAtomB() throws Exception { - Comment2000 cb = new Comment2000(data_b, 0, data_b.length); - Comment2000Atom c2b = cb.getComment2000Atom(); - - assertEquals(1, c2b.getNumber()); - assertEquals(0x0a, c2b.getXOffset()); - assertEquals(0x0a, c2b.getYOffset()); - Date exp_b = sdf.parse("2006-01-24 22:25:03.725"); - assertEquals(exp_b, c2b.getDate()); - } + Comment2000 cb = new Comment2000(data_b, 0, data_b.length); + Comment2000Atom c2b = cb.getComment2000Atom(); + + assertEquals(1, c2b.getNumber()); + assertEquals(0x0a, c2b.getXOffset()); + assertEquals(0x0a, c2b.getYOffset()); + Date exp_b = sdf.parse("2006-01-24 22:25:03.725"); + assertEquals(exp_b, c2b.getDate()); + } @Test void testWrite() throws Exception { - Comment2000 ca = new Comment2000(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ca.writeOut(baos); - byte[] b = baos.toByteArray(); - assertArrayEquals(data_a, b); - } - - // Change a few things + Comment2000 ca = new Comment2000(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ca.writeOut(baos); + byte[] b = baos.toByteArray(); + assertArrayEquals(data_a, b); + } + + // Change a few things @Test void testChange() throws Exception { - Comment2000 ca = new Comment2000(data_a, 0, data_a.length); - Comment2000 cb = new Comment2000(data_b, 0, data_b.length); - Comment2000 cn = new Comment2000(); - ca.setAuthor("Hogwarts"); - ca.setAuthorInitials("H"); - ca.setText("Comments are fun things to add in, aren't they?"); - cn.setAuthor("Hogwarts"); - cn.setAuthorInitials("H"); - cn.setText("Comments are fun things to add in, aren't they?"); - - // Change the Comment2000Atom - Comment2000Atom c2a = ca.getComment2000Atom(); - Comment2000Atom c2n = cn.getComment2000Atom(); - c2a.setNumber(1); - c2a.setXOffset(0x0a); - c2a.setYOffset(0x0a); - c2n.setNumber(1); - c2n.setXOffset(0x0a); - c2n.setYOffset(0x0a); - - Date new_date = sdf.parse("2006-01-24 22:25:03.725"); - c2a.setDate(new_date); - c2n.setDate(new_date); - - // Check now the same - assertEquals(ca.getText(), cb.getText()); - assertEquals(cn.getText(), cb.getText()); - assertEquals(ca.getAuthor(), cb.getAuthor()); - assertEquals(cn.getAuthor(), cb.getAuthor()); - assertEquals(ca.getAuthorInitials(), cb.getAuthorInitials()); - assertEquals(cn.getAuthorInitials(), cb.getAuthorInitials()); - - // Check bytes weren't the same - boolean equals = true; - for(int i=0; i<data_a.length; i++) { - if (data_a[i] != data_b[i]) { - equals = false; - break; - } - } - assertFalse(equals, "Arrays should not be equals"); - - // Check bytes are now the same - UnsynchronizedByteArrayOutputStream baosa = new UnsynchronizedByteArrayOutputStream(); - UnsynchronizedByteArrayOutputStream baosn = new UnsynchronizedByteArrayOutputStream(); - ca.writeOut(baosa); - cn.writeOut(baosn); - byte[] ba = baosa.toByteArray(); - byte[] bn = baosn.toByteArray(); - - // Should now be the same - assertArrayEquals(data_b, ba); - assertArrayEquals(data_b, bn); - } + Comment2000 ca = new Comment2000(data_a, 0, data_a.length); + Comment2000 cb = new Comment2000(data_b, 0, data_b.length); + Comment2000 cn = new Comment2000(); + ca.setAuthor("Hogwarts"); + ca.setAuthorInitials("H"); + ca.setText("Comments are fun things to add in, aren't they?"); + cn.setAuthor("Hogwarts"); + cn.setAuthorInitials("H"); + cn.setText("Comments are fun things to add in, aren't they?"); + + // Change the Comment2000Atom + Comment2000Atom c2a = ca.getComment2000Atom(); + Comment2000Atom c2n = cn.getComment2000Atom(); + c2a.setNumber(1); + c2a.setXOffset(0x0a); + c2a.setYOffset(0x0a); + c2n.setNumber(1); + c2n.setXOffset(0x0a); + c2n.setYOffset(0x0a); + + Date new_date = sdf.parse("2006-01-24 22:25:03.725"); + c2a.setDate(new_date); + c2n.setDate(new_date); + + // Check now the same + assertEquals(ca.getText(), cb.getText()); + assertEquals(cn.getText(), cb.getText()); + assertEquals(ca.getAuthor(), cb.getAuthor()); + assertEquals(cn.getAuthor(), cb.getAuthor()); + assertEquals(ca.getAuthorInitials(), cb.getAuthorInitials()); + assertEquals(cn.getAuthorInitials(), cb.getAuthorInitials()); + + // Check bytes weren't the same + boolean equals = true; + for(int i=0; i<data_a.length; i++) { + if (data_a[i] != data_b[i]) { + equals = false; + break; + } + } + assertFalse(equals, "Arrays should not be equals"); + + // Check bytes are now the same + UnsynchronizedByteArrayOutputStream baosa = new UnsynchronizedByteArrayOutputStream(); + UnsynchronizedByteArrayOutputStream baosn = new UnsynchronizedByteArrayOutputStream(); + ca.writeOut(baosa); + cn.writeOut(baosn); + byte[] ba = baosa.toByteArray(); + byte[] bn = baosn.toByteArray(); + + // Should now be the same + assertArrayEquals(data_b, ba); + assertArrayEquals(data_b, bn); + } /** * A Comment2000 records with missing commentTextAtom */ @Test void testBug44770() { - byte[] data = { + byte[] data = { 0x0F, 0x00, (byte)0xE0, 0x2E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xBA, 0x0F, 0x08, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x45, 0x00, 0x53, 0x00, 0x53, 0x00, 0x20, 0x00, (byte)0xBA, 0x0F, 0x02, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, (byte)0xE1, 0x2E, diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestComment2000Atom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestComment2000Atom.java index f3bbdcaa8f..734f3b73ad 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestComment2000Atom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestComment2000Atom.java @@ -34,21 +34,21 @@ import org.junit.jupiter.api.Test; * Tests that Comment2000Atom works properly. */ public final class TestComment2000Atom { - // From a real file - private final byte[] data_a = new byte[] { - 0, 0, 0xE1-256, 0x2E, 0x1C, 0, 0, 0, - 1, 0, 0, 0, 0xD6-256, 7, 1, 0, - 2, 0, 0x18, 0, 0x0A, 0, 0x1A, 0, - 0x0F, 0, 0xCD-256, 0, 0x92-256, 0, - 0, 0, 0x92-256, 0, 0, 0 - }; - private final byte[] data_b = new byte[] { - 0, 0, 0xE1-256, 0x2E, 0x1C, 0, 0, 0, - 5, 0, 0, 0, 0xD6-256, 0x07, 1, 0, - 2, 0, 0x18, 0, 0x15, 0, 0x19, 0, 3, - 0, 0xD5-256, 2, 0x0A, 0, 0, 0, - 0x0E, 0, 0, 0 - }; + // From a real file + private final byte[] data_a = new byte[] { + 0, 0, 0xE1-256, 0x2E, 0x1C, 0, 0, 0, + 1, 0, 0, 0, 0xD6-256, 7, 1, 0, + 2, 0, 0x18, 0, 0x0A, 0, 0x1A, 0, + 0x0F, 0, 0xCD-256, 0, 0x92-256, 0, + 0, 0, 0x92-256, 0, 0, 0 + }; + private final byte[] data_b = new byte[] { + 0, 0, 0xE1-256, 0x2E, 0x1C, 0, 0, 0, + 5, 0, 0, 0, 0xD6-256, 0x07, 1, 0, + 2, 0, 0x18, 0, 0x15, 0, 0x19, 0, 3, + 0, 0xD5-256, 2, 0x0A, 0, 0, 0, + 0x0E, 0, 0, 0 + }; private static SimpleDateFormat sdf; @@ -58,101 +58,101 @@ public final class TestComment2000Atom { sdf.setTimeZone(LocaleUtil.getUserTimeZone()); } - @Test - void testRecordType() { - Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); - assertEquals(12001L, ca.getRecordType()); - } + @Test + void testRecordType() { + Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); + assertEquals(12001L, ca.getRecordType()); + } - @Test + @Test void testGetDate() throws Exception { - Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); - Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length); + Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); + Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length); - // A is 2006-01-24 (2nd day of week) 10:26:15.205 - Date exp_a = sdf.parse("2006-01-24 10:26:15.205"); - // B is 2006-01-24 (2nd day of week) 21:25:03.725 - Date exp_b = sdf.parse("2006-01-24 21:25:03.725"); + // A is 2006-01-24 (2nd day of week) 10:26:15.205 + Date exp_a = sdf.parse("2006-01-24 10:26:15.205"); + // B is 2006-01-24 (2nd day of week) 21:25:03.725 + Date exp_b = sdf.parse("2006-01-24 21:25:03.725"); - assertEquals(exp_a, ca.getDate()); - assertEquals(exp_b, cb.getDate()); - } + assertEquals(exp_a, ca.getDate()); + assertEquals(exp_b, cb.getDate()); + } - @Test + @Test void testGetNums() { - Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); - Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length); + Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); + Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length); - // A is number 1 - assertEquals(1, ca.getNumber()); - // B is number 5 - assertEquals(5, cb.getNumber()); - } + // A is number 1 + assertEquals(1, ca.getNumber()); + // B is number 5 + assertEquals(5, cb.getNumber()); + } - @Test + @Test void testGetPos() { - Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); - Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length); + Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); + Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length); - // A is at 0x92, 0x92 - assertEquals(0x92, ca.getXOffset()); - assertEquals(0x92, ca.getYOffset()); + // A is at 0x92, 0x92 + assertEquals(0x92, ca.getXOffset()); + assertEquals(0x92, ca.getYOffset()); - // B is at 0x0A, 0x0E - assertEquals(0x0A, cb.getXOffset()); - assertEquals(0x0E, cb.getYOffset()); - } + // B is at 0x0A, 0x0E + assertEquals(0x0A, cb.getXOffset()); + assertEquals(0x0E, cb.getYOffset()); + } - @Test + @Test void testWrite() throws Exception { - Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ca.writeOut(baos); - byte[] b = baos.toByteArray(); - assertArrayEquals(data_a, b); - } - - // Create A from scratch - @Test + Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ca.writeOut(baos); + byte[] b = baos.toByteArray(); + assertArrayEquals(data_a, b); + } + + // Create A from scratch + @Test void testCreate() throws Exception { - Comment2000Atom a = new Comment2000Atom(); - - // Set number, x and y - a.setNumber(1); - a.setXOffset(0x92); - a.setYOffset(0x92); - - // Set the date - Date date_a = sdf.parse("2006-01-24 10:26:15.205"); - a.setDate(date_a); - - // Check it's now the same as a - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - a.writeOut(baos); - byte[] b = baos.toByteArray(); - assertArrayEquals(data_a, b); - } - - // Try to turn a into b - @Test + Comment2000Atom a = new Comment2000Atom(); + + // Set number, x and y + a.setNumber(1); + a.setXOffset(0x92); + a.setYOffset(0x92); + + // Set the date + Date date_a = sdf.parse("2006-01-24 10:26:15.205"); + a.setDate(date_a); + + // Check it's now the same as a + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + a.writeOut(baos); + byte[] b = baos.toByteArray(); + assertArrayEquals(data_a, b); + } + + // Try to turn a into b + @Test void testChange() throws Exception { - Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); + Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length); - // Change the number - ca.setNumber(5); + // Change the number + ca.setNumber(5); - // Change the date - Date new_date = sdf.parse("2006-01-24 21:25:03.725"); - ca.setDate(new_date); + // Change the date + Date new_date = sdf.parse("2006-01-24 21:25:03.725"); + ca.setDate(new_date); - // Change the x and y - ca.setXOffset(0x0A); - ca.setYOffset(0x0E); + // Change the x and y + ca.setXOffset(0x0A); + ca.setYOffset(0x0E); - // Check bytes are now the same - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ca.writeOut(baos); - byte[] b = baos.toByteArray(); - assertArrayEquals(data_b, b); - } + // Check bytes are now the same + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ca.writeOut(baos); + byte[] b = baos.toByteArray(); + assertArrayEquals(data_b, b); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCurrentUserAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCurrentUserAtom.java index b21e0d8b67..c8c0cc2eac 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCurrentUserAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCurrentUserAtom.java @@ -36,63 +36,63 @@ import org.junit.jupiter.api.Test; */ public final class TestCurrentUserAtom { private static final POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); - /** Not encrypted */ - private static final String normalFile = "basic_test_ppt_file.ppt"; - /** Encrypted */ - private static final String encFile = "Password_Protected-hello.ppt"; + /** Not encrypted */ + private static final String normalFile = "basic_test_ppt_file.ppt"; + /** Encrypted */ + private static final String encFile = "Password_Protected-hello.ppt"; - @Test - void readNormal() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_slTests.getFile(normalFile)); + @Test + void readNormal() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(_slTests.getFile(normalFile)); - CurrentUserAtom cu = new CurrentUserAtom(fs.getRoot()); - fs.close(); + CurrentUserAtom cu = new CurrentUserAtom(fs.getRoot()); + fs.close(); - // Check the contents - assertEquals("Hogwarts", cu.getLastEditUsername()); - assertEquals(0x2942, cu.getCurrentEditOffset()); + // Check the contents + assertEquals("Hogwarts", cu.getLastEditUsername()); + assertEquals(0x2942, cu.getCurrentEditOffset()); - // Round trip - POIFSFileSystem poifs = new POIFSFileSystem(); - cu.writeToFS(poifs); + // Round trip + POIFSFileSystem poifs = new POIFSFileSystem(); + cu.writeToFS(poifs); - CurrentUserAtom cu2 = new CurrentUserAtom(poifs.getRoot()); - assertEquals("Hogwarts", cu2.getLastEditUsername()); - assertEquals(0x2942, cu2.getCurrentEditOffset()); + CurrentUserAtom cu2 = new CurrentUserAtom(poifs.getRoot()); + assertEquals("Hogwarts", cu2.getLastEditUsername()); + assertEquals(0x2942, cu2.getCurrentEditOffset()); - poifs.close(); - } + poifs.close(); + } - @Test - void readEnc() throws Exception { + @Test + void readEnc() throws Exception { try (POIFSFileSystem fs = new POIFSFileSystem(_slTests.getFile(encFile))) { new CurrentUserAtom(fs.getRoot()); - assertThrows(EncryptedPowerPointFileException.class, () -> new HSLFSlideShowImpl(fs).close()); + assertThrows(EncryptedPowerPointFileException.class, () -> new HSLFSlideShowImpl(fs).close()); } - } - - @Test - void writeNormal() throws Exception { - // Get raw contents from a known file - byte[] contents; - try (POIFSFileSystem fs = new POIFSFileSystem(_slTests.getFile(normalFile))) { - DocumentEntry docProps = (DocumentEntry) fs.getRoot().getEntry("Current User"); - contents = new byte[docProps.getSize()]; - try (InputStream in = fs.getRoot().createDocumentInputStream("Current User")) { - in.read(contents); - } - } - - // Now build up a new one - CurrentUserAtom cu = new CurrentUserAtom(); - cu.setLastEditUsername("Hogwarts"); - cu.setCurrentEditOffset(0x2942); - - // Check it matches - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - cu.writeOut(baos); - byte[] out = baos.toByteArray(); - - assertArrayEquals(contents, out); - } + } + + @Test + void writeNormal() throws Exception { + // Get raw contents from a known file + byte[] contents; + try (POIFSFileSystem fs = new POIFSFileSystem(_slTests.getFile(normalFile))) { + DocumentEntry docProps = (DocumentEntry) fs.getRoot().getEntry("Current User"); + contents = new byte[docProps.getSize()]; + try (InputStream in = fs.getRoot().createDocumentInputStream("Current User")) { + in.read(contents); + } + } + + // Now build up a new one + CurrentUserAtom cu = new CurrentUserAtom(); + cu.setLastEditUsername("Hogwarts"); + cu.setCurrentEditOffset(0x2942); + + // Check it matches + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + cu.writeOut(baos); + byte[] out = baos.toByteArray(); + + assertArrayEquals(contents, out); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocument.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocument.java index 949a0c1ac4..ffcfd95956 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocument.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocument.java @@ -30,57 +30,57 @@ import org.junit.jupiter.api.Test; * Tests that Document works properly (Also tests Environment while we're at it) */ public final class TestDocument { - private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - - // HSLFSlideShow primed on the test data - private HSLFSlideShowImpl ss; - // POIFS primed on the test data - private POIFSFileSystem pfs; - - @BeforeEach - void setup() throws Exception { - pfs = new POIFSFileSystem(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new HSLFSlideShowImpl(pfs); - } - - private Document getDocRecord() { - Record[] r = ss.getRecords(); - for (int i = (r.length - 1); i >= 0; i--) { - if (r[i] instanceof Document) { - return (Document) r[i]; - } - } - throw new IllegalStateException("No Document record found"); - } - - @Test - void testRecordType() { - Document dr = getDocRecord(); - assertEquals(1000, dr.getRecordType()); - } - - @Test - void testChildRecords() { - Document dr = getDocRecord(); - assertNotNull(dr.getDocumentAtom()); - - assertNotNull(dr.getEnvironment()); - - assertNotNull(dr.getSlideListWithTexts()); - assertEquals(3, dr.getSlideListWithTexts().length); - assertNotNull(dr.getSlideListWithTexts()[0]); - assertNotNull(dr.getSlideListWithTexts()[1]); - assertNotNull(dr.getSlideListWithTexts()[2]); - } - - @Test - void testEnvironment() { - Document dr = getDocRecord(); - Environment env = dr.getEnvironment(); - - assertEquals(1010, env.getRecordType()); - assertNotNull(env.getFontCollection()); - } - - // No need to check re-writing - hslf.TestReWrite does all that for us + private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); + + // HSLFSlideShow primed on the test data + private HSLFSlideShowImpl ss; + // POIFS primed on the test data + private POIFSFileSystem pfs; + + @BeforeEach + void setup() throws Exception { + pfs = new POIFSFileSystem(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShowImpl(pfs); + } + + private Document getDocRecord() { + Record[] r = ss.getRecords(); + for (int i = (r.length - 1); i >= 0; i--) { + if (r[i] instanceof Document) { + return (Document) r[i]; + } + } + throw new IllegalStateException("No Document record found"); + } + + @Test + void testRecordType() { + Document dr = getDocRecord(); + assertEquals(1000, dr.getRecordType()); + } + + @Test + void testChildRecords() { + Document dr = getDocRecord(); + assertNotNull(dr.getDocumentAtom()); + + assertNotNull(dr.getEnvironment()); + + assertNotNull(dr.getSlideListWithTexts()); + assertEquals(3, dr.getSlideListWithTexts().length); + assertNotNull(dr.getSlideListWithTexts()[0]); + assertNotNull(dr.getSlideListWithTexts()[1]); + assertNotNull(dr.getSlideListWithTexts()[2]); + } + + @Test + void testEnvironment() { + Document dr = getDocRecord(); + Environment env = dr.getEnvironment(); + + assertEquals(1010, env.getRecordType()); + assertNotNull(env.getFontCollection()); + } + + // No need to check re-writing - hslf.TestReWrite does all that for us } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentAtom.java index c831a478c6..34f2480ffe 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentAtom.java @@ -30,59 +30,59 @@ import org.junit.jupiter.api.Test; * Tests that DocumentAtom works properly */ public final class TestDocumentAtom { - // From a real file - private final byte[] data_a = { 1, 0, 0xE9-256, 3, 0x28, 0, 0, 0, - 0x80-256, 0x16, 0, 0, 0xE0-256, 0x10, 0, 0, - 0xE0-256, 0x10, 0, 0, 0x80-256, 0x16, 0, 0, - 0x05, 0, 0, 0, 0x0A, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 1 }; + // From a real file + private final byte[] data_a = { 1, 0, 0xE9-256, 3, 0x28, 0, 0, 0, + 0x80-256, 0x16, 0, 0, 0xE0-256, 0x10, 0, 0, + 0xE0-256, 0x10, 0, 0, 0x80-256, 0x16, 0, 0, + 0x05, 0, 0, 0, 0x0A, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 1 }; - @Test + @Test void testRecordType() { - DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); - assertEquals(1001L, da.getRecordType()); - } + DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); + assertEquals(1001L, da.getRecordType()); + } - @Test - void testSizeAndZoom() { - DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); - assertEquals(5760L, da.getSlideSizeX()); - assertEquals(4320L, da.getSlideSizeY()); - assertEquals(4320L, da.getNotesSizeX()); - assertEquals(5760L, da.getNotesSizeY()); + @Test + void testSizeAndZoom() { + DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); + assertEquals(5760L, da.getSlideSizeX()); + assertEquals(4320L, da.getSlideSizeY()); + assertEquals(4320L, da.getNotesSizeX()); + assertEquals(5760L, da.getNotesSizeY()); - assertEquals(5L, da.getServerZoomFrom()); - assertEquals(10L, da.getServerZoomTo()); - } + assertEquals(5L, da.getServerZoomFrom()); + assertEquals(10L, da.getServerZoomTo()); + } - @Test - void testMasterPersist() { - DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); - assertEquals(2L, da.getNotesMasterPersist()); - assertEquals(0L, da.getHandoutMasterPersist()); - } + @Test + void testMasterPersist() { + DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); + assertEquals(2L, da.getNotesMasterPersist()); + assertEquals(0L, da.getHandoutMasterPersist()); + } - @Test - void testSlideDetails() { - DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); - assertEquals(1, da.getFirstSlideNum()); - assertEquals(DocumentAtom.SlideSize.ON_SCREEN, da.getSlideSizeTypeEnum()); - } + @Test + void testSlideDetails() { + DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); + assertEquals(1, da.getFirstSlideNum()); + assertEquals(DocumentAtom.SlideSize.ON_SCREEN, da.getSlideSizeTypeEnum()); + } - @Test - void testBooleans() { - DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); + @Test + void testBooleans() { + DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); assertFalse(da.getSaveWithFonts()); assertFalse(da.getOmitTitlePlace()); assertFalse(da.getRightToLeft()); assertTrue(da.getShowComments()); - } + } - @Test - void testWrite() throws Exception { - DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - da.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } + @Test + void testWrite() throws Exception { + DocumentAtom da = new DocumentAtom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + da.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentEncryptionAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentEncryptionAtom.java index c33507c404..eb1c6fba04 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentEncryptionAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentEncryptionAtom.java @@ -28,82 +28,82 @@ import org.junit.jupiter.api.Test; * Tests that DocumentEncryptionAtom works properly. */ public final class TestDocumentEncryptionAtom { - // From a real file - private final byte[] data_a = new byte[] { - 0x0F, 00, 0x14, 0x2F, 0xBE-256, 00, 00, 00, - 02, 00, 02, 00, 0x0C, 00, 00, 00, - 0x76, 00, 00, 00, 0x0C, 00, 00, 00, - 00, 00, 00, 00, 01, 0x68, 00, 00, - 04, 0x80-256, 00, 00, 0x28, 00, 00, 00, - 01, 00, 00, 00, 0x30, 00, 0x26, 01, - 00, 00, 00, 00, - - 0x4D, 00, 0x69, 00, - 0x63, 00, 0x72, 00, 0x6F, 00, 0x73, 00, - 0x6F, 00, 0x66, 00, 0x74, 00, 0x20, 00, - 0x42, 00, 0x61, 00, 0x73, 00, 0x65, 00, - 0x20, 00, 0x43, 00, 0x72, 00, 0x79, 00, - 0x70, 00, 0x74, 00, 0x6F, 00, 0x67, 00, - 0x72, 00, 0x61, 00, 0x70, 00, 0x68, 00, - 0x69, 00, 0x63, 00, 0x20, 00, 0x50, 00, - 0x72, 00, 0x6F, 00, 0x76, 00, 0x69, 00, - 0x64, 00, 0x65, 00, 0x72, 00, 0x20, 00, - 0x76, 00, 0x31, 00, 0x2E, 00, 0x30, 00, - 0x00, 0x00, - - 0x10, 00, 0x00, 00, - 0x62, 0xA6-256, - 0xDF-256, 0xEA-256, 0x96-256, 0x84-256, - 0xFB-256, 0x89-256, 0x93-256, 0xCA-256, - 0xBA-256, 0xEE-256, 0x8E-256, 0x43, - 0xC8-256, 0x71, 0xD1-256, 0x89-256, - 0xF6-256, 0x4B, 0x2B, 0xD9-256, - 0x7E, 0x0B, 0x52, 0xFB-256, - 0x68, 0xD7-256, 0x5A, 0x4E, 0x45, 0xDF-256, 0x14, 0x00, - 0x00, 0x00, 0x93-256, 0x15, 0x27, 0xEB-256, 0x21, 0x54, - 0x7F, 0x0B, 0x56, 0x07, 0xEE-256, 0x66, 0xEB-256, 0x6F, - 0xB2-256, 0x8E-256, 0x67, 0x54, 0x07, 0x04, 0x00 - }; - - private final byte[] data_b = new byte[] { - 15, 0, 20, 47, -66, 0, 0, 0, - 2, 0, 2, 0, 4, - 0, 0, 0, 118, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, - 0, 1, 104, 0, 0, 4, -128, 0, 0, 56, 0, 0, 0, - 1, 0, 0, 0, 48, 0, 38, 1, 0, 0, 0, 0, 77, 0, - 105, 0, 99, 0, 114, 0, 111, 0, 115, 0, 111, - 0, 102, 0, 116, 0, 32, 0, 66, 0, 97, 0, 115, - 0, 101, 0, 32, 0, 67, 0, 114, 0, 121, 0, 112, - 0, 116, 0, 111, 0, 103, 0, 114, 0, 97, 0, - 112, 0, 104, 0, 105, 0, 99, 0, 32, 0, 80, 0, - 114, 0, 111, 0, 118, 0, 105, 0, 100, 0, 101, - 0, 114, 0, 32, 0, 118, 0, 49, 0, 46, 0, 48, - 0, 0, 0, 16, 0, 0, 0, -80, -66, 112, -40, 57, - 110, 54, 80, 64, 61, -73, -29, 48, -35, -20, - 17, -40, 84, 54, 6, -103, 125, -22, -72, 53, - 103, -114, 13, -48, 111, 29, 78, 20, 0, 0, - 0, -97, -67, 55, -62, -94, 14, 15, -21, 37, - 3, -104, 22, 6, 102, -61, -98, 62, 40, 61, 21 - }; - - @Test + // From a real file + private final byte[] data_a = new byte[] { + 0x0F, 00, 0x14, 0x2F, 0xBE-256, 00, 00, 00, + 02, 00, 02, 00, 0x0C, 00, 00, 00, + 0x76, 00, 00, 00, 0x0C, 00, 00, 00, + 00, 00, 00, 00, 01, 0x68, 00, 00, + 04, 0x80-256, 00, 00, 0x28, 00, 00, 00, + 01, 00, 00, 00, 0x30, 00, 0x26, 01, + 00, 00, 00, 00, + + 0x4D, 00, 0x69, 00, + 0x63, 00, 0x72, 00, 0x6F, 00, 0x73, 00, + 0x6F, 00, 0x66, 00, 0x74, 00, 0x20, 00, + 0x42, 00, 0x61, 00, 0x73, 00, 0x65, 00, + 0x20, 00, 0x43, 00, 0x72, 00, 0x79, 00, + 0x70, 00, 0x74, 00, 0x6F, 00, 0x67, 00, + 0x72, 00, 0x61, 00, 0x70, 00, 0x68, 00, + 0x69, 00, 0x63, 00, 0x20, 00, 0x50, 00, + 0x72, 00, 0x6F, 00, 0x76, 00, 0x69, 00, + 0x64, 00, 0x65, 00, 0x72, 00, 0x20, 00, + 0x76, 00, 0x31, 00, 0x2E, 00, 0x30, 00, + 0x00, 0x00, + + 0x10, 00, 0x00, 00, + 0x62, 0xA6-256, + 0xDF-256, 0xEA-256, 0x96-256, 0x84-256, + 0xFB-256, 0x89-256, 0x93-256, 0xCA-256, + 0xBA-256, 0xEE-256, 0x8E-256, 0x43, + 0xC8-256, 0x71, 0xD1-256, 0x89-256, + 0xF6-256, 0x4B, 0x2B, 0xD9-256, + 0x7E, 0x0B, 0x52, 0xFB-256, + 0x68, 0xD7-256, 0x5A, 0x4E, 0x45, 0xDF-256, 0x14, 0x00, + 0x00, 0x00, 0x93-256, 0x15, 0x27, 0xEB-256, 0x21, 0x54, + 0x7F, 0x0B, 0x56, 0x07, 0xEE-256, 0x66, 0xEB-256, 0x6F, + 0xB2-256, 0x8E-256, 0x67, 0x54, 0x07, 0x04, 0x00 + }; + + private final byte[] data_b = new byte[] { + 15, 0, 20, 47, -66, 0, 0, 0, + 2, 0, 2, 0, 4, + 0, 0, 0, 118, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 1, 104, 0, 0, 4, -128, 0, 0, 56, 0, 0, 0, + 1, 0, 0, 0, 48, 0, 38, 1, 0, 0, 0, 0, 77, 0, + 105, 0, 99, 0, 114, 0, 111, 0, 115, 0, 111, + 0, 102, 0, 116, 0, 32, 0, 66, 0, 97, 0, 115, + 0, 101, 0, 32, 0, 67, 0, 114, 0, 121, 0, 112, + 0, 116, 0, 111, 0, 103, 0, 114, 0, 97, 0, + 112, 0, 104, 0, 105, 0, 99, 0, 32, 0, 80, 0, + 114, 0, 111, 0, 118, 0, 105, 0, 100, 0, 101, + 0, 114, 0, 32, 0, 118, 0, 49, 0, 46, 0, 48, + 0, 0, 0, 16, 0, 0, 0, -80, -66, 112, -40, 57, + 110, 54, 80, 64, 61, -73, -29, 48, -35, -20, + 17, -40, 84, 54, 6, -103, 125, -22, -72, 53, + 103, -114, 13, -48, 111, 29, 78, 20, 0, 0, + 0, -97, -67, 55, -62, -94, 14, 15, -21, 37, + 3, -104, 22, 6, 102, -61, -98, 62, 40, 61, 21 + }; + + @Test void recordType() throws IOException { - DocumentEncryptionAtom dea1 = new DocumentEncryptionAtom(data_a, 0, data_a.length); - assertEquals(12052l, dea1.getRecordType()); + DocumentEncryptionAtom dea1 = new DocumentEncryptionAtom(data_a, 0, data_a.length); + assertEquals(12052l, dea1.getRecordType()); - DocumentEncryptionAtom dea2 = new DocumentEncryptionAtom(data_b, 0, data_b.length); - assertEquals(12052l, dea2.getRecordType()); + DocumentEncryptionAtom dea2 = new DocumentEncryptionAtom(data_b, 0, data_b.length); + assertEquals(12052l, dea2.getRecordType()); - assertEquals(199, data_a.length); - assertEquals(198, data_b.length); - } + assertEquals(199, data_a.length); + assertEquals(198, data_b.length); + } - @Test + @Test void encryptionTypeName() throws IOException { - DocumentEncryptionAtom dea1 = new DocumentEncryptionAtom(data_a, 0, data_a.length); - assertEquals("Microsoft Base Cryptographic Provider v1.0", dea1.getEncryptionProviderName()); + DocumentEncryptionAtom dea1 = new DocumentEncryptionAtom(data_a, 0, data_a.length); + assertEquals("Microsoft Base Cryptographic Provider v1.0", dea1.getEncryptionProviderName()); - DocumentEncryptionAtom dea2 = new DocumentEncryptionAtom(data_b, 0, data_b.length); - assertEquals("Microsoft Base Cryptographic Provider v1.0", dea2.getEncryptionProviderName()); + DocumentEncryptionAtom dea2 = new DocumentEncryptionAtom(data_b, 0, data_b.length); + assertEquals("Microsoft Base Cryptographic Provider v1.0", dea2.getEncryptionProviderName()); } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExControl.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExControl.java index 2faa7ebfd8..2b1cfa3bda 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExControl.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExControl.java @@ -30,7 +30,7 @@ import org.junit.jupiter.api.Test; */ public final class TestExControl { - // From a real file (embedded SWF control) + // From a real file (embedded SWF control) /* <ExControl info="15" type="4078" size="218" offset="76" header="0F 00 EE 0F DA 00 00 00 "> <ExControlAtom info="0" type="4091" size="4" offset="84" header="00 00 FB 0F 04 00 00 00 "> @@ -70,53 +70,53 @@ public final class TestExControl { 0x65, 0x00, 0x63, 0x00, 0x74, 0x00 }; - @Test - void testRead() { - ExControl record = new ExControl(data, 0, data.length); - assertEquals(RecordTypes.ExControl.typeID, record.getRecordType()); - - assertNotNull(record.getExControlAtom()); - assertEquals(256, record.getExControlAtom().getSlideId()); - - ExOleObjAtom oleObj = record.getExOleObjAtom(); - assertNotNull(oleObj); - assertEquals(oleObj.getDrawAspect(), ExOleObjAtom.DRAW_ASPECT_VISIBLE); - assertEquals(oleObj.getType(), ExOleObjAtom.TYPE_CONTROL); - assertEquals(oleObj.getSubType(), ExOleObjAtom.SUBTYPE_DEFAULT); - - assertEquals("Shockwave Flash Object", record.getMenuName()); - assertEquals("ShockwaveFlash.ShockwaveFlash.9", record.getProgId()); - assertEquals("Shockwave Flash Object", record.getClipboardName()); - } - - @Test - void testWrite() throws Exception { - ExControl record = new ExControl(data, 0, data.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - record.writeOut(baos); - assertArrayEquals(data, baos.toByteArray()); - } - - @Test - void testNewRecord() throws Exception { - ExControl record = new ExControl(); - ExControlAtom ctrl = record.getExControlAtom(); - ctrl.setSlideId(256); - - ExOleObjAtom oleObj = record.getExOleObjAtom(); - oleObj.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); - oleObj.setType(ExOleObjAtom.TYPE_CONTROL); - oleObj.setObjID(1); - oleObj.setSubType(ExOleObjAtom.SUBTYPE_DEFAULT); - oleObj.setObjStgDataRef(2); - oleObj.setOptions(1283584); - - record.setMenuName("Shockwave Flash Object"); - record.setProgId("ShockwaveFlash.ShockwaveFlash.9"); - record.setClipboardName("Shockwave Flash Object"); - - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - record.writeOut(baos); - assertArrayEquals(data, baos.toByteArray()); - } + @Test + void testRead() { + ExControl record = new ExControl(data, 0, data.length); + assertEquals(RecordTypes.ExControl.typeID, record.getRecordType()); + + assertNotNull(record.getExControlAtom()); + assertEquals(256, record.getExControlAtom().getSlideId()); + + ExOleObjAtom oleObj = record.getExOleObjAtom(); + assertNotNull(oleObj); + assertEquals(oleObj.getDrawAspect(), ExOleObjAtom.DRAW_ASPECT_VISIBLE); + assertEquals(oleObj.getType(), ExOleObjAtom.TYPE_CONTROL); + assertEquals(oleObj.getSubType(), ExOleObjAtom.SUBTYPE_DEFAULT); + + assertEquals("Shockwave Flash Object", record.getMenuName()); + assertEquals("ShockwaveFlash.ShockwaveFlash.9", record.getProgId()); + assertEquals("Shockwave Flash Object", record.getClipboardName()); + } + + @Test + void testWrite() throws Exception { + ExControl record = new ExControl(data, 0, data.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + record.writeOut(baos); + assertArrayEquals(data, baos.toByteArray()); + } + + @Test + void testNewRecord() throws Exception { + ExControl record = new ExControl(); + ExControlAtom ctrl = record.getExControlAtom(); + ctrl.setSlideId(256); + + ExOleObjAtom oleObj = record.getExOleObjAtom(); + oleObj.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); + oleObj.setType(ExOleObjAtom.TYPE_CONTROL); + oleObj.setObjID(1); + oleObj.setSubType(ExOleObjAtom.SUBTYPE_DEFAULT); + oleObj.setObjStgDataRef(2); + oleObj.setOptions(1283584); + + record.setMenuName("Shockwave Flash Object"); + record.setProgId("ShockwaveFlash.ShockwaveFlash.9"); + record.setClipboardName("Shockwave Flash Object"); + + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + record.writeOut(baos); + assertArrayEquals(data, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExHyperlink.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExHyperlink.java index 42a9867560..d67a9db105 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExHyperlink.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExHyperlink.java @@ -36,17 +36,17 @@ import org.junit.jupiter.api.Test; * Tests that ExHyperlink works properly. */ public final class TestExHyperlink { - @Test + @Test void testReadWrite() throws IOException { // From a real file byte[] exHyperlinkBytes = org.apache.poi.poifs.storage.RawDataUtil.decompress( "H4sIAAAAAAAAAONnuM6/ggEELvOzAElmMHsXvxuQzGAoAcICBisGfSDMYkhkyAbi"+ "IqBYIoMeEBcAcTJQVSqQlw8UTweqKgCyMoF0BkMxEKYBWQJUNQ0A/k1x3rAAAAA=" ); - ExHyperlink exHyperlink = new ExHyperlink(exHyperlinkBytes, 0, exHyperlinkBytes.length); + ExHyperlink exHyperlink = new ExHyperlink(exHyperlinkBytes, 0, exHyperlinkBytes.length); - assertEquals(4055L, exHyperlink.getRecordType()); + assertEquals(4055L, exHyperlink.getRecordType()); assertEquals(3, exHyperlink.getExHyperlinkAtom().getNumber()); String expURL = "http://jakarta.apache.org/poi/hssf/"; assertEquals(expURL, exHyperlink.getLinkURL()); @@ -56,56 +56,56 @@ public final class TestExHyperlink { UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); exHyperlink.writeOut(baos); assertArrayEquals(exHyperlinkBytes, baos.toByteArray()); - } + } - @Test - void testRealFile() throws IOException { + @Test + void testRealFile() throws IOException { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("WithLinks.ppt")); - HSLFSlideShow ss = new HSLFSlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("WithLinks.ppt")); + HSLFSlideShow ss = new HSLFSlideShow(hss); - // Get the document - Document doc = ss.getDocumentRecord(); - // Get the ExObjList - ExObjList exObjList = null; - for (final Record rec : doc._children) { - if(rec instanceof ExObjList) { - exObjList = (ExObjList)rec; - } - } + // Get the document + Document doc = ss.getDocumentRecord(); + // Get the ExObjList + ExObjList exObjList = null; + for (final Record rec : doc._children) { + if(rec instanceof ExObjList) { + exObjList = (ExObjList)rec; + } + } - assertNotNull(exObjList); + assertNotNull(exObjList); - // Within that, grab out the Hyperlink atoms - List<ExHyperlink> linksA = new ArrayList<>(); - for (Record ch : exObjList._children) { - if(ch instanceof ExHyperlink) { - linksA.add((ExHyperlink) ch); - } - } + // Within that, grab out the Hyperlink atoms + List<ExHyperlink> linksA = new ArrayList<>(); + for (Record ch : exObjList._children) { + if(ch instanceof ExHyperlink) { + linksA.add((ExHyperlink) ch); + } + } - // Should be 4 of them - assertEquals(4, linksA.size()); - ExHyperlink[] links = new ExHyperlink[linksA.size()]; - linksA.toArray(links); + // Should be 4 of them + assertEquals(4, linksA.size()); + ExHyperlink[] links = new ExHyperlink[linksA.size()]; + linksA.toArray(links); - assertEquals(4, exObjList.getExHyperlinks().length); + assertEquals(4, exObjList.getExHyperlinks().length); - // Check the other way + // Check the other way - // Check they have what we expect in them - assertEquals(1, links[0].getExHyperlinkAtom().getNumber()); - assertEquals("http://jakarta.apache.org/poi/", links[0].getLinkURL()); + // Check they have what we expect in them + assertEquals(1, links[0].getExHyperlinkAtom().getNumber()); + assertEquals("http://jakarta.apache.org/poi/", links[0].getLinkURL()); - assertEquals(2, links[1].getExHyperlinkAtom().getNumber()); - assertEquals("http://slashdot.org/", links[1].getLinkURL()); + assertEquals(2, links[1].getExHyperlinkAtom().getNumber()); + assertEquals("http://slashdot.org/", links[1].getLinkURL()); - assertEquals(3, links[2].getExHyperlinkAtom().getNumber()); - assertEquals("http://jakarta.apache.org/poi/hssf/", links[2].getLinkURL()); + assertEquals(3, links[2].getExHyperlinkAtom().getNumber()); + assertEquals("http://jakarta.apache.org/poi/hssf/", links[2].getLinkURL()); - assertEquals(4, links[3].getExHyperlinkAtom().getNumber()); - assertEquals("http://jakarta.apache.org/hslf/", links[3].getLinkURL()); + assertEquals(4, links[3].getExHyperlinkAtom().getNumber()); + assertEquals("http://jakarta.apache.org/hslf/", links[3].getLinkURL()); - ss.close(); - } + ss.close(); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExHyperlinkAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExHyperlinkAtom.java index f868d96b16..f738f44ec8 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExHyperlinkAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExHyperlinkAtom.java @@ -28,64 +28,64 @@ import org.junit.jupiter.api.Test; * Tests that ExHyperlinkAtom works properly. */ public class TestExHyperlinkAtom { - // From a real file - private final byte[] data_a = new byte[] { - 0, 0, 0xD3-256, 0x0F, 4, 0, 0, 0, - 1, 0, 0, 0 - }; - private final byte[] data_b = new byte[] { - 0, 0, 0xD3-256, 0x0F, 4, 0, 0, 0, - 4, 0, 0, 0 - }; - - @Test + // From a real file + private final byte[] data_a = new byte[] { + 0, 0, 0xD3-256, 0x0F, 4, 0, 0, 0, + 1, 0, 0, 0 + }; + private final byte[] data_b = new byte[] { + 0, 0, 0xD3-256, 0x0F, 4, 0, 0, 0, + 4, 0, 0, 0 + }; + + @Test void testRecordType() { - ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length); - assertEquals(4051L, eha.getRecordType()); - } + ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length); + assertEquals(4051L, eha.getRecordType()); + } - @Test + @Test void testGetNumber() { - ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length); - ExHyperlinkAtom ehb = new ExHyperlinkAtom(data_b, 0, data_b.length); + ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length); + ExHyperlinkAtom ehb = new ExHyperlinkAtom(data_b, 0, data_b.length); + + assertEquals(1, eha.getNumber()); + assertEquals(4, ehb.getNumber()); + } + + @Test + void testWrite() throws Exception { + ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + eha.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } - assertEquals(1, eha.getNumber()); - assertEquals(4, ehb.getNumber()); + // Create A from scratch + @Test + void testCreate() throws Exception { + ExHyperlinkAtom eha = new ExHyperlinkAtom(); + + // Set value + eha.setNumber(1); + + // Check it's now the same as a + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + eha.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); } - @Test - void testWrite() throws Exception { - ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - eha.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } - - // Create A from scratch - @Test - void testCreate() throws Exception { - ExHyperlinkAtom eha = new ExHyperlinkAtom(); - - // Set value - eha.setNumber(1); - - // Check it's now the same as a - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - eha.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } - - // Try to turn a into b - @Test - void testChange() throws Exception { - ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length); - - // Change the number - eha.setNumber(4); - - // Check bytes are now the same - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - eha.writeOut(baos); - assertArrayEquals(data_b, baos.toByteArray()); - } + // Try to turn a into b + @Test + void testChange() throws Exception { + ExHyperlinkAtom eha = new ExHyperlinkAtom(data_a, 0, data_a.length); + + // Change the number + eha.setNumber(4); + + // Check bytes are now the same + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + eha.writeOut(baos); + assertArrayEquals(data_b, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExMediaAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExMediaAtom.java index 606f0ac827..6d7e08c6a9 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExMediaAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExMediaAtom.java @@ -30,68 +30,68 @@ import org.junit.jupiter.api.Test; * Tests that {@link org.apache.poi.hslf.record.HeadersFootersAtom} works properly */ public final class TestExMediaAtom { - // From a real file - private static final byte[] data = { - 0x00, 0x00, (byte)0x04, 0x10, 0x08, 0x00, 0x00, 0, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - @Test - void testRead() { - ExMediaAtom record = new ExMediaAtom(data, 0, data.length); - assertEquals(RecordTypes.ExMediaAtom.typeID, record.getRecordType()); - - assertEquals(1, record.getObjectId()); - assertFalse(record.getFlag(ExMediaAtom.fLoop)); - assertFalse(record.getFlag(ExMediaAtom.fNarration)); - assertFalse(record.getFlag(ExMediaAtom.fRewind)); - } - - @Test - void testWrite() throws Exception { - ExMediaAtom record = new ExMediaAtom(data, 0, data.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - record.writeOut(baos); - byte[] b = baos.toByteArray(); - - assertArrayEquals(data, b); - } - - @Test - void testNewRecord() throws Exception { - ExMediaAtom ref = new ExMediaAtom(data, 0, data.length); - assertEquals(0, ref.getMask()); // - - ExMediaAtom record = new ExMediaAtom(); - record.setObjectId(1); - record.setFlag(HeadersFootersAtom.fHasDate, false); - record.setFlag(HeadersFootersAtom.fHasTodayDate, false); - record.setFlag(HeadersFootersAtom.fHasFooter, false); - - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - record.writeOut(baos); - byte[] b = baos.toByteArray(); - - assertArrayEquals(data, b); - } - - @Test - void testFlags() { - ExMediaAtom record = new ExMediaAtom(); - - //in a new record all the bits are 0 - for(int i = 0; i < 3; i++) assertFalse(record.getFlag(1 << i)); - - record.setFlag(ExMediaAtom.fLoop, true); - assertTrue(record.getFlag(ExMediaAtom.fLoop)); - - record.setFlag(ExMediaAtom.fNarration, true); - assertTrue(record.getFlag(ExMediaAtom.fNarration)); - - record.setFlag(ExMediaAtom.fNarration, false); - assertFalse(record.getFlag(ExMediaAtom.fNarration)); - - record.setFlag(ExMediaAtom.fNarration, false); - assertFalse(record.getFlag(ExMediaAtom.fNarration)); - - } + // From a real file + private static final byte[] data = { + 0x00, 0x00, (byte)0x04, 0x10, 0x08, 0x00, 0x00, 0, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + @Test + void testRead() { + ExMediaAtom record = new ExMediaAtom(data, 0, data.length); + assertEquals(RecordTypes.ExMediaAtom.typeID, record.getRecordType()); + + assertEquals(1, record.getObjectId()); + assertFalse(record.getFlag(ExMediaAtom.fLoop)); + assertFalse(record.getFlag(ExMediaAtom.fNarration)); + assertFalse(record.getFlag(ExMediaAtom.fRewind)); + } + + @Test + void testWrite() throws Exception { + ExMediaAtom record = new ExMediaAtom(data, 0, data.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + record.writeOut(baos); + byte[] b = baos.toByteArray(); + + assertArrayEquals(data, b); + } + + @Test + void testNewRecord() throws Exception { + ExMediaAtom ref = new ExMediaAtom(data, 0, data.length); + assertEquals(0, ref.getMask()); // + + ExMediaAtom record = new ExMediaAtom(); + record.setObjectId(1); + record.setFlag(HeadersFootersAtom.fHasDate, false); + record.setFlag(HeadersFootersAtom.fHasTodayDate, false); + record.setFlag(HeadersFootersAtom.fHasFooter, false); + + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + record.writeOut(baos); + byte[] b = baos.toByteArray(); + + assertArrayEquals(data, b); + } + + @Test + void testFlags() { + ExMediaAtom record = new ExMediaAtom(); + + //in a new record all the bits are 0 + for(int i = 0; i < 3; i++) assertFalse(record.getFlag(1 << i)); + + record.setFlag(ExMediaAtom.fLoop, true); + assertTrue(record.getFlag(ExMediaAtom.fLoop)); + + record.setFlag(ExMediaAtom.fNarration, true); + assertTrue(record.getFlag(ExMediaAtom.fNarration)); + + record.setFlag(ExMediaAtom.fNarration, false); + assertFalse(record.getFlag(ExMediaAtom.fNarration)); + + record.setFlag(ExMediaAtom.fNarration, false); + assertFalse(record.getFlag(ExMediaAtom.fNarration)); + + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExObjList.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExObjList.java index 0301b61463..56cc3ed677 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExObjList.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExObjList.java @@ -32,38 +32,38 @@ public class TestExObjList { @Test void testRealFile() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShow ss = new HSLFSlideShow(slTests.openResourceAsStream("WithLinks.ppt")); + HSLFSlideShow ss = new HSLFSlideShow(slTests.openResourceAsStream("WithLinks.ppt")); - // Get the document - Document doc = ss.getDocumentRecord(); - // Get the ExObjList - ExObjList exObjList = doc.getExObjList(false); - assertNotNull(exObjList); - assertEquals(1033l, exObjList.getRecordType()); + // Get the document + Document doc = ss.getDocumentRecord(); + // Get the ExObjList + ExObjList exObjList = doc.getExObjList(false); + assertNotNull(exObjList); + assertEquals(1033l, exObjList.getRecordType()); - // Check the atom - assertNotNull(exObjList.getExObjListAtom()); - assertEquals(4, exObjList.getExObjListAtom().getObjectIDSeed()); + // Check the atom + assertNotNull(exObjList.getExObjListAtom()); + assertEquals(4, exObjList.getExObjListAtom().getObjectIDSeed()); - // Check the Hyperlinks - assertEquals(4, exObjList.getExHyperlinks().length); + // Check the Hyperlinks + assertEquals(4, exObjList.getExHyperlinks().length); - // Check the contents - ExHyperlink[] links = exObjList.getExHyperlinks(); + // Check the contents + ExHyperlink[] links = exObjList.getExHyperlinks(); - // Check they have what we expect in them - assertEquals(1, links[0].getExHyperlinkAtom().getNumber()); - assertEquals("http://jakarta.apache.org/poi/", links[0].getLinkURL()); + // Check they have what we expect in them + assertEquals(1, links[0].getExHyperlinkAtom().getNumber()); + assertEquals("http://jakarta.apache.org/poi/", links[0].getLinkURL()); - assertEquals(2, links[1].getExHyperlinkAtom().getNumber()); - assertEquals("http://slashdot.org/", links[1].getLinkURL()); + assertEquals(2, links[1].getExHyperlinkAtom().getNumber()); + assertEquals("http://slashdot.org/", links[1].getLinkURL()); - assertEquals(3, links[2].getExHyperlinkAtom().getNumber()); - assertEquals("http://jakarta.apache.org/poi/hssf/", links[2].getLinkURL()); + assertEquals(3, links[2].getExHyperlinkAtom().getNumber()); + assertEquals("http://jakarta.apache.org/poi/hssf/", links[2].getLinkURL()); - assertEquals(4, links[3].getExHyperlinkAtom().getNumber()); - assertEquals("http://jakarta.apache.org/hslf/", links[3].getLinkURL()); + assertEquals(4, links[3].getExHyperlinkAtom().getNumber()); + assertEquals("http://jakarta.apache.org/hslf/", links[3].getLinkURL()); - ss.close(); - } + ss.close(); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExObjListAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExObjListAtom.java index 97d3ef1707..d8a5229aba 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExObjListAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExObjListAtom.java @@ -28,64 +28,64 @@ import org.junit.jupiter.api.Test; * Tests that ExObjListAtom works properly. */ public class TestExObjListAtom { - // From a real file - private final byte[] data_a = new byte[] { - 0, 0, 0x0A, 0x04, 4, 0, 0, 0, - 1, 0, 0, 0 - }; - private final byte[] data_b = new byte[] { - 0, 0, 0x0A, 0x04, 4, 0, 0, 0, - 4, 0, 0, 0 - }; - - @Test - void testRecordType() { - ExObjListAtom eoa = new ExObjListAtom(data_a, 0, data_a.length); - BaseTestNumeric.assertDouble(1034L, eoa.getRecordType()); - } - - @Test - void testGetSeed() { - ExObjListAtom eoa = new ExObjListAtom(data_a, 0, data_a.length); - ExObjListAtom eob = new ExObjListAtom(data_b, 0, data_b.length); - - BaseTestNumeric.assertDouble(1, eoa.getObjectIDSeed()); - BaseTestNumeric.assertDouble(4, eob.getObjectIDSeed()); - } - - @Test - void testWrite() throws Exception { - ExObjListAtom eoa = new ExObjListAtom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - eoa.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } - - // Create A from scratch - @Test - void testCreate() throws Exception { - ExObjListAtom eoa = new ExObjListAtom(); - - // Set seed - eoa.setObjectIDSeed(1); - - // Check it's now the same as a - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - eoa.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } - - // Try to turn a into b - @Test - void testChange() throws Exception { - ExObjListAtom eoa = new ExObjListAtom(data_a, 0, data_a.length); - - // Change the number - eoa.setObjectIDSeed(4); - - // Check bytes are now the same - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - eoa.writeOut(baos); - assertArrayEquals(data_b, baos.toByteArray()); - } + // From a real file + private final byte[] data_a = new byte[] { + 0, 0, 0x0A, 0x04, 4, 0, 0, 0, + 1, 0, 0, 0 + }; + private final byte[] data_b = new byte[] { + 0, 0, 0x0A, 0x04, 4, 0, 0, 0, + 4, 0, 0, 0 + }; + + @Test + void testRecordType() { + ExObjListAtom eoa = new ExObjListAtom(data_a, 0, data_a.length); + BaseTestNumeric.assertDouble(1034L, eoa.getRecordType()); + } + + @Test + void testGetSeed() { + ExObjListAtom eoa = new ExObjListAtom(data_a, 0, data_a.length); + ExObjListAtom eob = new ExObjListAtom(data_b, 0, data_b.length); + + BaseTestNumeric.assertDouble(1, eoa.getObjectIDSeed()); + BaseTestNumeric.assertDouble(4, eob.getObjectIDSeed()); + } + + @Test + void testWrite() throws Exception { + ExObjListAtom eoa = new ExObjListAtom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + eoa.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } + + // Create A from scratch + @Test + void testCreate() throws Exception { + ExObjListAtom eoa = new ExObjListAtom(); + + // Set seed + eoa.setObjectIDSeed(1); + + // Check it's now the same as a + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + eoa.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } + + // Try to turn a into b + @Test + void testChange() throws Exception { + ExObjListAtom eoa = new ExObjListAtom(data_a, 0, data_a.length); + + // Change the number + eoa.setObjectIDSeed(4); + + // Check bytes are now the same + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + eoa.writeOut(baos); + assertArrayEquals(data_b, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExOleObjAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExOleObjAtom.java index a0860abbbe..01d72f3265 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExOleObjAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExOleObjAtom.java @@ -27,45 +27,45 @@ import org.junit.jupiter.api.Test; * Tests that {@link ExOleObjAtom} works properly */ public final class TestExOleObjAtom { - // From a real file (embedded SWF control) - private final byte[] data = { - 0x01, 0x00, (byte)0xC3, 0x0F, 0x18, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, (byte)0x96, 0x13, 0x00 }; + // From a real file (embedded SWF control) + private final byte[] data = { + 0x01, 0x00, (byte)0xC3, 0x0F, 0x18, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, (byte)0x96, 0x13, 0x00 }; - @Test - void testRead() { - ExOleObjAtom record = new ExOleObjAtom(data, 0, data.length); - assertEquals(RecordTypes.ExOleObjAtom.typeID, record.getRecordType()); + @Test + void testRead() { + ExOleObjAtom record = new ExOleObjAtom(data, 0, data.length); + assertEquals(RecordTypes.ExOleObjAtom.typeID, record.getRecordType()); - assertEquals(record.getDrawAspect(), ExOleObjAtom.DRAW_ASPECT_VISIBLE); - assertEquals(record.getType(), ExOleObjAtom.TYPE_CONTROL); - assertEquals(record.getObjID(), 1); - assertEquals(record.getSubType(), ExOleObjAtom.SUBTYPE_DEFAULT); - assertEquals(record.getObjStgDataRef(), 2); - assertEquals(record.getOptions(), 1283584); //ther meaning is unknown - } + assertEquals(record.getDrawAspect(), ExOleObjAtom.DRAW_ASPECT_VISIBLE); + assertEquals(record.getType(), ExOleObjAtom.TYPE_CONTROL); + assertEquals(record.getObjID(), 1); + assertEquals(record.getSubType(), ExOleObjAtom.SUBTYPE_DEFAULT); + assertEquals(record.getObjStgDataRef(), 2); + assertEquals(record.getOptions(), 1283584); //ther meaning is unknown + } - @Test - void testWrite() throws Exception { - ExOleObjAtom record = new ExOleObjAtom(data, 0, data.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - record.writeOut(baos); - assertArrayEquals(data, baos.toByteArray()); - } + @Test + void testWrite() throws Exception { + ExOleObjAtom record = new ExOleObjAtom(data, 0, data.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + record.writeOut(baos); + assertArrayEquals(data, baos.toByteArray()); + } - @Test - void testNewRecord() throws Exception { - ExOleObjAtom record = new ExOleObjAtom(); - record.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); - record.setType(ExOleObjAtom.TYPE_CONTROL); - record.setObjID(1); - record.setSubType(ExOleObjAtom.SUBTYPE_DEFAULT); - record.setObjStgDataRef(2); - record.setOptions(1283584); + @Test + void testNewRecord() throws Exception { + ExOleObjAtom record = new ExOleObjAtom(); + record.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); + record.setType(ExOleObjAtom.TYPE_CONTROL); + record.setObjID(1); + record.setSubType(ExOleObjAtom.SUBTYPE_DEFAULT); + record.setObjStgDataRef(2); + record.setOptions(1283584); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - record.writeOut(baos); - assertArrayEquals(data, baos.toByteArray()); - } + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + record.writeOut(baos); + assertArrayEquals(data, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestHeadersFootersAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestHeadersFootersAtom.java index 7277fc4790..71ea592da2 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestHeadersFootersAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestHeadersFootersAtom.java @@ -30,15 +30,15 @@ import org.junit.jupiter.api.Test; * Tests that {@link HeadersFootersAtom} works properly */ public final class TestHeadersFootersAtom { - // From a real file - private final byte[] data = new byte[] { + // From a real file + private final byte[] data = new byte[] { 0x00, 0x00, (byte)0xDA, 0x0F, 0x04, 0x00, 0x00, 0, 0x00, 0x00, 0x23, 0x00 }; @Test void testRead() { - HeadersFootersAtom record = new HeadersFootersAtom(data, 0, data.length); - assertEquals(RecordTypes.HeadersFootersAtom.typeID, record.getRecordType()); + HeadersFootersAtom record = new HeadersFootersAtom(data, 0, data.length); + assertEquals(RecordTypes.HeadersFootersAtom.typeID, record.getRecordType()); assertEquals(0, record.getFormatId()); assertEquals(0x23, record.getMask()); @@ -52,12 +52,12 @@ public final class TestHeadersFootersAtom { } @Test - void testWrite() throws Exception { - HeadersFootersAtom record = new HeadersFootersAtom(data, 0, data.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - record.writeOut(baos); - assertArrayEquals(data, baos.toByteArray()); - } + void testWrite() throws Exception { + HeadersFootersAtom record = new HeadersFootersAtom(data, 0, data.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + record.writeOut(baos); + assertArrayEquals(data, baos.toByteArray()); + } @Test void testNewRecord() throws Exception { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestHeadersFootersContainer.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestHeadersFootersContainer.java index 5d6d15b798..21d7a83d16 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestHeadersFootersContainer.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestHeadersFootersContainer.java @@ -30,8 +30,8 @@ import org.junit.jupiter.api.Test; * Tests that {@link HeadersFootersContainer} works properly */ public final class TestHeadersFootersContainer { - // SlideHeadersFootersContainer - private final byte[] slideData = new byte[] { + // SlideHeadersFootersContainer + private final byte[] slideData = new byte[] { 0x3F, 0x00, (byte)0xD9, 0x0F, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xDA, 0x0F, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x20, 0x00, (byte)0xBA, 0x0F, 0x1A, 0x00, 0x00, 0x00, @@ -54,8 +54,8 @@ public final class TestHeadersFootersContainer { @Test void testReadSlideHeadersFootersContainer() { - HeadersFootersContainer record = new HeadersFootersContainer(slideData, 0, slideData.length); - assertEquals(RecordTypes.HeadersFooters.typeID, record.getRecordType()); + HeadersFootersContainer record = new HeadersFootersContainer(slideData, 0, slideData.length); + assertEquals(RecordTypes.HeadersFooters.typeID, record.getRecordType()); assertEquals(HeadersFootersContainer.SlideHeadersFootersContainer, record.getOptions()); assertEquals(2, record.getChildRecords().length); @@ -73,12 +73,12 @@ public final class TestHeadersFootersContainer { } @Test - void testWriteSlideHeadersFootersContainer() throws Exception { - HeadersFootersContainer record = new HeadersFootersContainer(slideData, 0, slideData.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - record.writeOut(baos); - assertArrayEquals(slideData, baos.toByteArray()); - } + void testWriteSlideHeadersFootersContainer() throws Exception { + HeadersFootersContainer record = new HeadersFootersContainer(slideData, 0, slideData.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + record.writeOut(baos); + assertArrayEquals(slideData, baos.toByteArray()); + } @Test void testNewSlideHeadersFootersContainer() throws Exception { @@ -106,8 +106,8 @@ public final class TestHeadersFootersContainer { @Test void testReadNotesHeadersFootersContainer() { - HeadersFootersContainer record = new HeadersFootersContainer(notesData, 0, notesData.length); - assertEquals(RecordTypes.HeadersFooters.typeID, record.getRecordType()); + HeadersFootersContainer record = new HeadersFootersContainer(notesData, 0, notesData.length); + assertEquals(RecordTypes.HeadersFooters.typeID, record.getRecordType()); assertEquals(HeadersFootersContainer.NotesHeadersFootersContainer, record.getOptions()); assertEquals(3, record.getChildRecords().length); @@ -126,12 +126,12 @@ public final class TestHeadersFootersContainer { } @Test - void testWriteNotesHeadersFootersContainer() throws Exception { - HeadersFootersContainer record = new HeadersFootersContainer(notesData, 0, notesData.length); + void testWriteNotesHeadersFootersContainer() throws Exception { + HeadersFootersContainer record = new HeadersFootersContainer(notesData, 0, notesData.length); UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - record.writeOut(baos); - assertArrayEquals(notesData, baos.toByteArray()); - } + record.writeOut(baos); + assertArrayEquals(notesData, baos.toByteArray()); + } @Test void testNewNotesHeadersFootersContainer() throws Exception { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestInteractiveInfo.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestInteractiveInfo.java index 1b1ab55491..3e003969a9 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestInteractiveInfo.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestInteractiveInfo.java @@ -31,51 +31,51 @@ import org.junit.jupiter.api.Test; * Tests that InteractiveInfoAtom works properly. */ public class TestInteractiveInfo { - // From a real file - private final byte[] data_a = { - 0x0F, 0, 0xF2-256, 0x0F, 0x18, 0, 0, 0, - 0, 0, 0xF3-256, 0x0F, 0x10, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, - 4, 0, 0, 0, 8, 0, 0, 0 - }; - - @Test - void testRecordType() { - InteractiveInfo ii = new InteractiveInfo(data_a, 0, data_a.length); - assertEquals(4082, ii.getRecordType()); - } - - @Test - void testGetChildDetails() { - InteractiveInfo ii = new InteractiveInfo(data_a, 0, data_a.length); - InteractiveInfoAtom ia = ii.getInteractiveInfoAtom(); - - assertEquals(1, ia.getHyperlinkID()); - } - - @Test - void testWrite() throws Exception { - InteractiveInfo ii = new InteractiveInfo(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ii.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } - - // Create A from scratch - @Test - void testCreate() throws Exception { - InteractiveInfo ii = new InteractiveInfo(); - InteractiveInfoAtom ia = ii.getInteractiveInfoAtom(); - - // Set values - ia.setHyperlinkID(1); - ia.setSoundRef(0); - ia.setAction((byte)4); - ia.setHyperlinkType((byte)8); - - // Check it's now the same as a - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ii.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); + // From a real file + private final byte[] data_a = { + 0x0F, 0, 0xF2-256, 0x0F, 0x18, 0, 0, 0, + 0, 0, 0xF3-256, 0x0F, 0x10, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 4, 0, 0, 0, 8, 0, 0, 0 + }; + + @Test + void testRecordType() { + InteractiveInfo ii = new InteractiveInfo(data_a, 0, data_a.length); + assertEquals(4082, ii.getRecordType()); + } + + @Test + void testGetChildDetails() { + InteractiveInfo ii = new InteractiveInfo(data_a, 0, data_a.length); + InteractiveInfoAtom ia = ii.getInteractiveInfoAtom(); + + assertEquals(1, ia.getHyperlinkID()); + } + + @Test + void testWrite() throws Exception { + InteractiveInfo ii = new InteractiveInfo(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ii.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } + + // Create A from scratch + @Test + void testCreate() throws Exception { + InteractiveInfo ii = new InteractiveInfo(); + InteractiveInfoAtom ia = ii.getInteractiveInfoAtom(); + + // Set values + ia.setHyperlinkID(1); + ia.setSoundRef(0); + ia.setAction((byte)4); + ia.setHyperlinkType((byte)8); + + // Check it's now the same as a + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ii.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestInteractiveInfoAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestInteractiveInfoAtom.java index 9eeab59618..824cfce1fd 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestInteractiveInfoAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestInteractiveInfoAtom.java @@ -28,84 +28,84 @@ import org.junit.jupiter.api.Test; * Tests that InteractiveInfoAtom works properly. */ public class TestInteractiveInfoAtom { - // From a real file - private final byte[] data_a = new byte[] { - 0, 0, 0xF3-256, 0x0F, 0x10, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, - 4, 0, 0, 0, 8, 0, 0, 0 - }; - private final byte[] data_b = new byte[] { - 0, 0, 0xF3-256, 0x0F, 0x10, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 0, - 4, 0, 0, 0, 8, 0, 0, 0 - }; - - @Test - void testRecordType() { - InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); - assertEquals(4083L, ia.getRecordType()); - } - - @Test - void testGetNumber() { - InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); - InteractiveInfoAtom ib = new InteractiveInfoAtom(data_b, 0, data_b.length); - - assertEquals(1, ia.getHyperlinkID()); - assertEquals(4, ib.getHyperlinkID()); - } - - @Test - void testGetRest() { - InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); - InteractiveInfoAtom ib = new InteractiveInfoAtom(data_b, 0, data_b.length); - - assertEquals(0, ia.getSoundRef()); - assertEquals(0, ib.getSoundRef()); - - assertEquals(4, ia.getAction()); - assertEquals(4, ib.getAction()); - - assertEquals(8, ia.getHyperlinkType()); - assertEquals(8, ib.getHyperlinkType()); - } - - @Test - void testWrite() throws Exception { - InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ia.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } - - // Create A from scratch - @Test - void testCreate() throws Exception { - InteractiveInfoAtom ia = new InteractiveInfoAtom(); - - // Set values - ia.setHyperlinkID(1); - ia.setSoundRef(0); - ia.setAction((byte)4); - ia.setHyperlinkType((byte)8); - - // Check it's now the same as a - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ia.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } - - // Try to turn a into b - @Test - void testChange() throws Exception { - InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); - - // Change the number - ia.setHyperlinkID(4); - - // Check bytes are now the same - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ia.writeOut(baos); - assertArrayEquals(data_b, baos.toByteArray()); - } + // From a real file + private final byte[] data_a = new byte[] { + 0, 0, 0xF3-256, 0x0F, 0x10, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 4, 0, 0, 0, 8, 0, 0, 0 + }; + private final byte[] data_b = new byte[] { + 0, 0, 0xF3-256, 0x0F, 0x10, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 8, 0, 0, 0 + }; + + @Test + void testRecordType() { + InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); + assertEquals(4083L, ia.getRecordType()); + } + + @Test + void testGetNumber() { + InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); + InteractiveInfoAtom ib = new InteractiveInfoAtom(data_b, 0, data_b.length); + + assertEquals(1, ia.getHyperlinkID()); + assertEquals(4, ib.getHyperlinkID()); + } + + @Test + void testGetRest() { + InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); + InteractiveInfoAtom ib = new InteractiveInfoAtom(data_b, 0, data_b.length); + + assertEquals(0, ia.getSoundRef()); + assertEquals(0, ib.getSoundRef()); + + assertEquals(4, ia.getAction()); + assertEquals(4, ib.getAction()); + + assertEquals(8, ia.getHyperlinkType()); + assertEquals(8, ib.getHyperlinkType()); + } + + @Test + void testWrite() throws Exception { + InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ia.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } + + // Create A from scratch + @Test + void testCreate() throws Exception { + InteractiveInfoAtom ia = new InteractiveInfoAtom(); + + // Set values + ia.setHyperlinkID(1); + ia.setSoundRef(0); + ia.setAction((byte)4); + ia.setHyperlinkType((byte)8); + + // Check it's now the same as a + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ia.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } + + // Try to turn a into b + @Test + void testChange() throws Exception { + InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length); + + // Change the number + ia.setHyperlinkID(4); + + // Check bytes are now the same + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ia.writeOut(baos); + assertArrayEquals(data_b, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestNotesAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestNotesAtom.java index d122f019dd..5528d26293 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestNotesAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestNotesAtom.java @@ -29,30 +29,30 @@ import org.junit.jupiter.api.Test; * Tests that NotesAtom works properly */ public final class TestNotesAtom { - // From a real file - private final byte[] data_a = new byte[] { 1, 0, 0xF1-256, 3, 8, 0, 0, 0, - 0, 0, 0, 0x80-256, 0, 0, 0x0D, 0x30 }; - - @Test - void testRecordType() { - NotesAtom na = new NotesAtom(data_a, 0, data_a.length); - assertEquals(1009L, na.getRecordType()); - } - - @Test - void testFlags() { - NotesAtom na = new NotesAtom(data_a, 0, data_a.length); - assertEquals(0x80000000, na.getSlideID()); + // From a real file + private final byte[] data_a = new byte[] { 1, 0, 0xF1-256, 3, 8, 0, 0, 0, + 0, 0, 0, 0x80-256, 0, 0, 0x0D, 0x30 }; + + @Test + void testRecordType() { + NotesAtom na = new NotesAtom(data_a, 0, data_a.length); + assertEquals(1009L, na.getRecordType()); + } + + @Test + void testFlags() { + NotesAtom na = new NotesAtom(data_a, 0, data_a.length); + assertEquals(0x80000000, na.getSlideID()); assertFalse(na.getFollowMasterObjects()); assertFalse(na.getFollowMasterScheme()); assertFalse(na.getFollowMasterBackground()); - } - - @Test - void testWrite() throws Exception { - NotesAtom na = new NotesAtom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - na.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } + } + + @Test + void testWrite() throws Exception { + NotesAtom na = new NotesAtom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + na.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestRecordContainer.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestRecordContainer.java index dccb8f2cad..49c4061887 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestRecordContainer.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestRecordContainer.java @@ -36,7 +36,7 @@ import org.junit.jupiter.api.Test; */ public final class TestRecordContainer { private HSLFSlideShowImpl hss; - private RecordContainer recordContainer; + private RecordContainer recordContainer; private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); @BeforeEach @@ -60,115 +60,115 @@ public final class TestRecordContainer { hss.close(); } - @Test - void testIsAnAtom() { - assertFalse( recordContainer.isAnAtom() ); - } + @Test + void testIsAnAtom() { + assertFalse( recordContainer.isAnAtom() ); + } @Test - void testAppendChildRecord() { - // Grab records for testing with - Record r = recordContainer.getChildRecords()[0]; - Record rb = recordContainer.getChildRecords()[1]; - Record rc = recordContainer.getChildRecords()[2]; - Record rd = recordContainer.getChildRecords()[3]; - - // Start with an empty set - Record[] rs = new Record[0]; - recordContainer._children = rs; - recordContainer.appendChildRecord(r); - Record[] nrs = recordContainer.getChildRecords(); - - assertEquals(1, nrs.length); - assertEquals(r, nrs[0]); - - // Now start with one with 3 entries - rs = new Record[3]; - recordContainer._children = rs; - rs[0] = rb; - rs[1] = rc; - rs[2] = rd; - - recordContainer.appendChildRecord(r); - nrs = recordContainer.getChildRecords(); - - assertEquals(4, nrs.length); - assertEquals(rb, nrs[0]); - assertEquals(rc, nrs[1]); - assertEquals(rd, nrs[2]); - assertEquals(r, nrs[3]); - } + void testAppendChildRecord() { + // Grab records for testing with + Record r = recordContainer.getChildRecords()[0]; + Record rb = recordContainer.getChildRecords()[1]; + Record rc = recordContainer.getChildRecords()[2]; + Record rd = recordContainer.getChildRecords()[3]; + + // Start with an empty set + Record[] rs = new Record[0]; + recordContainer._children = rs; + recordContainer.appendChildRecord(r); + Record[] nrs = recordContainer.getChildRecords(); + + assertEquals(1, nrs.length); + assertEquals(r, nrs[0]); + + // Now start with one with 3 entries + rs = new Record[3]; + recordContainer._children = rs; + rs[0] = rb; + rs[1] = rc; + rs[2] = rd; + + recordContainer.appendChildRecord(r); + nrs = recordContainer.getChildRecords(); + + assertEquals(4, nrs.length); + assertEquals(rb, nrs[0]); + assertEquals(rc, nrs[1]); + assertEquals(rd, nrs[2]); + assertEquals(r, nrs[3]); + } @Test - void testAddChildAfter() { - // Working with new StyleTextPropAtom - Record newRecord = new StyleTextPropAtom(0); + void testAddChildAfter() { + // Working with new StyleTextPropAtom + Record newRecord = new StyleTextPropAtom(0); - // Try to add after a mid-record - Record[] cr = recordContainer.getChildRecords(); - Record after = cr[2]; - Record before = cr[3]; + // Try to add after a mid-record + Record[] cr = recordContainer.getChildRecords(); + Record after = cr[2]; + Record before = cr[3]; - recordContainer.addChildAfter(newRecord, after); - Record[] ncr = recordContainer.getChildRecords(); + recordContainer.addChildAfter(newRecord, after); + Record[] ncr = recordContainer.getChildRecords(); - assertEquals(cr.length+1, ncr.length); - assertEquals(after, ncr[2]); - assertEquals(newRecord, ncr[3]); - assertEquals(before, ncr[4]); + assertEquals(cr.length+1, ncr.length); + assertEquals(after, ncr[2]); + assertEquals(newRecord, ncr[3]); + assertEquals(before, ncr[4]); - // Try again at the end - recordContainer._children = cr; - after = cr[cr.length-1]; + // Try again at the end + recordContainer._children = cr; + after = cr[cr.length-1]; - recordContainer.addChildAfter(newRecord, after); - ncr = recordContainer.getChildRecords(); + recordContainer.addChildAfter(newRecord, after); + ncr = recordContainer.getChildRecords(); - assertEquals(cr.length+1, ncr.length); - assertEquals(after, ncr[cr.length-1]); - assertEquals(newRecord, ncr[cr.length]); - } + assertEquals(cr.length+1, ncr.length); + assertEquals(after, ncr[cr.length-1]); + assertEquals(newRecord, ncr[cr.length]); + } @Test - void testAddChildBefore() { - // Working with new StyleTextPropAtom - Record newRecord = new StyleTextPropAtom(0); + void testAddChildBefore() { + // Working with new StyleTextPropAtom + Record newRecord = new StyleTextPropAtom(0); - // Try to add before a mid-record - Record[] cr = recordContainer.getChildRecords(); - Record before = cr[2]; + // Try to add before a mid-record + Record[] cr = recordContainer.getChildRecords(); + Record before = cr[2]; - recordContainer.addChildBefore(newRecord, before); - Record[] ncr = recordContainer.getChildRecords(); + recordContainer.addChildBefore(newRecord, before); + Record[] ncr = recordContainer.getChildRecords(); - assertEquals(cr.length+1, ncr.length); - assertEquals(newRecord, ncr[2]); - assertEquals(before, ncr[3]); + assertEquals(cr.length+1, ncr.length); + assertEquals(newRecord, ncr[2]); + assertEquals(before, ncr[3]); - // Try again at the end - recordContainer._children = cr; - before = cr[cr.length-1]; + // Try again at the end + recordContainer._children = cr; + before = cr[cr.length-1]; - recordContainer.addChildBefore(newRecord, before); - ncr = recordContainer.getChildRecords(); + recordContainer.addChildBefore(newRecord, before); + ncr = recordContainer.getChildRecords(); - assertEquals(cr.length+1, ncr.length); - assertEquals(newRecord, ncr[cr.length-1]); - assertEquals(before, ncr[cr.length]); + assertEquals(cr.length+1, ncr.length); + assertEquals(newRecord, ncr[cr.length-1]); + assertEquals(before, ncr[cr.length]); - // And at the start - recordContainer._children = cr; - before = cr[0]; + // And at the start + recordContainer._children = cr; + before = cr[0]; - recordContainer.addChildBefore(newRecord, before); - ncr = recordContainer.getChildRecords(); + recordContainer.addChildBefore(newRecord, before); + ncr = recordContainer.getChildRecords(); - assertEquals(cr.length+1, ncr.length); - assertEquals(newRecord, ncr[0]); - assertEquals(before, ncr[1]); - } + assertEquals(cr.length+1, ncr.length); + assertEquals(newRecord, ncr[0]); + assertEquals(before, ncr[1]); + } @Test void testRemove() { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestRecordTypes.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestRecordTypes.java index 869dc427d7..a3c52a7060 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestRecordTypes.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestRecordTypes.java @@ -28,23 +28,23 @@ import org.junit.jupiter.api.Test; */ public final class TestRecordTypes { @Test - void testPPTNameLookups() { - assertEquals("MainMaster", RecordTypes.MainMaster.name()); - assertEquals("TextBytesAtom", RecordTypes.TextBytesAtom.name()); - assertEquals("VBAInfo", RecordTypes.VBAInfo.name()); - } + void testPPTNameLookups() { + assertEquals("MainMaster", RecordTypes.MainMaster.name()); + assertEquals("TextBytesAtom", RecordTypes.TextBytesAtom.name()); + assertEquals("VBAInfo", RecordTypes.VBAInfo.name()); + } @Test - void testEscherNameLookups() { - assertEquals("DGG_CONTAINER", EscherRecordTypes.DGG_CONTAINER.name()); - assertEquals("CLIENT_TEXTBOX", EscherRecordTypes.CLIENT_TEXTBOX.name()); - assertEquals("SELECTION", EscherRecordTypes.SELECTION.name()); - } + void testEscherNameLookups() { + assertEquals("DGG_CONTAINER", EscherRecordTypes.DGG_CONTAINER.name()); + assertEquals("CLIENT_TEXTBOX", EscherRecordTypes.CLIENT_TEXTBOX.name()); + assertEquals("SELECTION", EscherRecordTypes.SELECTION.name()); + } @Test - void testPPTClassLookups() { - // If this record is ever implemented, change to one that isn't! - // This is checking the "unhandled default" stuff works - assertEquals(RecordTypes.UnknownRecordPlaceholder, RecordTypes.forTypeID(-10)); - } + void testPPTClassLookups() { + // If this record is ever implemented, change to one that isn't! + // This is checking the "unhandled default" stuff works + assertEquals(RecordTypes.UnknownRecordPlaceholder, RecordTypes.forTypeID(-10)); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSlideAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSlideAtom.java index 7f67088716..366f85310f 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSlideAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSlideAtom.java @@ -35,63 +35,63 @@ import org.junit.jupiter.api.Test; * Tests that SlideAtom works properly */ public final class TestSlideAtom { - // From a real file - private static final byte[] data_a = new byte[] { 1, 0, 0xEF-256, 3, 0x18, 0, 0, 0, - 0, 0, 0, 0, 0x0F, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80-256, - 0, 1, 0, 0, 7, 0, 0x0C, 0x30 }; + // From a real file + private static final byte[] data_a = new byte[] { 1, 0, 0xEF-256, 3, 0x18, 0, 0, 0, + 0, 0, 0, 0, 0x0F, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80-256, + 0, 1, 0, 0, 7, 0, 0x0C, 0x30 }; - @Test - void testRecordType() { - SlideAtom sa = new SlideAtom(data_a, 0, data_a.length); - assertEquals(1007L, sa.getRecordType()); - } + @Test + void testRecordType() { + SlideAtom sa = new SlideAtom(data_a, 0, data_a.length); + assertEquals(1007L, sa.getRecordType()); + } @Test - void testFlags() { - SlideAtom sa = new SlideAtom(data_a, 0, data_a.length); + void testFlags() { + SlideAtom sa = new SlideAtom(data_a, 0, data_a.length); - // First 12 bytes are a SSlideLayoutAtom, checked elsewhere + // First 12 bytes are a SSlideLayoutAtom, checked elsewhere - // Check the IDs - assertEquals(SlideAtom.USES_MASTER_SLIDE_ID, sa.getMasterID()); - assertEquals(256, sa.getNotesID()); + // Check the IDs + assertEquals(SlideAtom.USES_MASTER_SLIDE_ID, sa.getMasterID()); + assertEquals(256, sa.getNotesID()); - // Check the flags + // Check the flags assertTrue(sa.getFollowMasterObjects()); assertTrue(sa.getFollowMasterScheme()); assertTrue(sa.getFollowMasterBackground()); - } + } @Test void testSSlideLayoutAtom() { - SlideAtom sa = new SlideAtom(data_a, 0, data_a.length); - SlideAtomLayout ssla = sa.getSSlideLayoutAtom(); + SlideAtom sa = new SlideAtom(data_a, 0, data_a.length); + SlideAtomLayout ssla = sa.getSSlideLayoutAtom(); - assertEquals(SlideLayoutType.TITLE_SLIDE, ssla.getGeometryType()); + assertEquals(SlideLayoutType.TITLE_SLIDE, ssla.getGeometryType()); - // Should also check the placeholder IDs at some point - } + // Should also check the placeholder IDs at some point + } @Test - void testWrite() throws IOException { - SlideAtom sa = new SlideAtom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - sa.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } + void testWrite() throws IOException { + SlideAtom sa = new SlideAtom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + sa.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } @Test - void testSSSlideInfoAtom() throws IOException { - try (HSLFSlideShow ppt1 = new HSLFSlideShow()) { - HSLFSlide slide1 = ppt1.createSlide(), slide2 = ppt1.createSlide(); - slide2.setHidden(true); - - try (HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1)) { - slide1 = ppt2.getSlides().get(0); - slide2 = ppt2.getSlides().get(1); - assertFalse(slide1.isHidden()); - assertTrue(slide2.isHidden()); - } - } - } + void testSSSlideInfoAtom() throws IOException { + try (HSLFSlideShow ppt1 = new HSLFSlideShow()) { + HSLFSlide slide1 = ppt1.createSlide(), slide2 = ppt1.createSlide(); + slide2.setHidden(true); + + try (HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1)) { + slide1 = ppt2.getSlides().get(0); + slide2 = ppt2.getSlides().get(1); + assertFalse(slide1.isHidden()); + assertTrue(slide2.isHidden()); + } + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSlidePersistAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSlidePersistAtom.java index d5f1105f47..4e0386d1ca 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSlidePersistAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSlidePersistAtom.java @@ -29,31 +29,31 @@ import org.junit.jupiter.api.Test; * Tests that SlidePersistAtom works properly */ public final class TestSlidePersistAtom { - // From a real file - private final byte[] data_a = new byte[] { 0, 0, 0xF3-256, 3, 0x14, 0, 0, 0, - 4, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0 }; - - @Test - void testRecordType() { - SlidePersistAtom spa = new SlidePersistAtom(data_a, 0, data_a.length); - assertEquals(1011L, spa.getRecordType()); - } - - @Test - void testFlags() { - SlidePersistAtom spa = new SlidePersistAtom(data_a, 0, data_a.length); - assertEquals(4, spa.getRefID() ); + // From a real file + private final byte[] data_a = new byte[] { 0, 0, 0xF3-256, 3, 0x14, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0 }; + + @Test + void testRecordType() { + SlidePersistAtom spa = new SlidePersistAtom(data_a, 0, data_a.length); + assertEquals(1011L, spa.getRecordType()); + } + + @Test + void testFlags() { + SlidePersistAtom spa = new SlidePersistAtom(data_a, 0, data_a.length); + assertEquals(4, spa.getRefID() ); assertTrue(spa.getHasShapesOtherThanPlaceholders()); - assertEquals(2, spa.getNumPlaceholderTexts() ); - assertEquals(256, spa.getSlideIdentifier()); - } - - @Test - void testWrite() throws Exception { - SlidePersistAtom spa = new SlidePersistAtom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - spa.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } + assertEquals(2, spa.getNumPlaceholderTexts() ); + assertEquals(256, spa.getSlideIdentifier()); + } + + @Test + void testWrite() throws Exception { + SlidePersistAtom spa = new SlidePersistAtom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + spa.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSound.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSound.java index 4bfbc23526..5fcdf2f79f 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSound.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestSound.java @@ -33,43 +33,43 @@ import org.junit.jupiter.api.Test; */ public final class TestSound { @Test - void testRealFile() throws IOException { + void testRealFile() throws IOException { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("sound.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("sound.ppt")); - // Get the document - Document doc = ppt.getDocumentRecord(); - SoundCollection soundCollection = null; - Record[] doc_ch = doc.getChildRecords(); - for ( org.apache.poi.hslf.record.Record rec : doc_ch) { - if (rec instanceof SoundCollection) { - soundCollection = (SoundCollection) rec; - break; - } - } - assertNotNull(soundCollection); + // Get the document + Document doc = ppt.getDocumentRecord(); + SoundCollection soundCollection = null; + Record[] doc_ch = doc.getChildRecords(); + for ( org.apache.poi.hslf.record.Record rec : doc_ch) { + if (rec instanceof SoundCollection) { + soundCollection = (SoundCollection) rec; + break; + } + } + assertNotNull(soundCollection); - Sound sound = null; - Record[] sound_ch = soundCollection.getChildRecords(); - int k = 0; - for ( org.apache.poi.hslf.record.Record rec : sound_ch) { - if (rec instanceof Sound) { - sound = (Sound) rec; - k++; - } - } + Sound sound = null; + Record[] sound_ch = soundCollection.getChildRecords(); + int k = 0; + for ( org.apache.poi.hslf.record.Record rec : sound_ch) { + if (rec instanceof Sound) { + sound = (Sound) rec; + k++; + } + } - assertNotNull(sound); - assertEquals(1, k); + assertNotNull(sound); + assertEquals(1, k); - assertEquals("ringin.wav", sound.getSoundName()); - assertEquals(".WAV", sound.getSoundType()); - assertNotNull(sound.getSoundData()); + assertEquals("ringin.wav", sound.getSoundName()); + assertEquals(".WAV", sound.getSoundType()); + assertNotNull(sound.getSoundData()); - byte[] ref_data = slTests.readFile("ringin.wav"); - assertArrayEquals(ref_data, sound.getSoundData()); + byte[] ref_data = slTests.readFile("ringin.wav"); + assertArrayEquals(ref_data, sound.getSoundData()); - ppt.close(); + ppt.close(); } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextBytesAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextBytesAtom.java index c06eff77d1..d50fc18a92 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextBytesAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextBytesAtom.java @@ -30,50 +30,50 @@ import org.junit.jupiter.api.Test; * Tests that TextBytesAtom works properly */ public final class TestTextBytesAtom { - // From a real file - private final byte[] data = { 0, 0, 0xA8-256, 0x0f, 0x1c, 0, 0, 0, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x20, 0x6F, 0x6E, - 0x20, 0x70, 0x61, 0x67, 0x65, 0x20, 0x32 }; - private final byte[] alt_data = { 0, 0, 0xA8-256, 0x0F, 0x14, 0, 0, 0, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, - 0x74, 0x65, 0x73, 0x74, 0x20, 0x74, 0x69, 0x74, 0x6C, 0x65 }; - private final String alt_text = "This is a test title"; + // From a real file + private final byte[] data = { 0, 0, 0xA8-256, 0x0f, 0x1c, 0, 0, 0, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x20, 0x6F, 0x6E, + 0x20, 0x70, 0x61, 0x67, 0x65, 0x20, 0x32 }; + private final byte[] alt_data = { 0, 0, 0xA8-256, 0x0F, 0x14, 0, 0, 0, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, + 0x74, 0x65, 0x73, 0x74, 0x20, 0x74, 0x69, 0x74, 0x6C, 0x65 }; + private final String alt_text = "This is a test title"; - @Test + @Test void testRecordType() { - TextBytesAtom tba = new TextBytesAtom(data,0,data.length); - assertEquals(4008L, tba.getRecordType()); - } + TextBytesAtom tba = new TextBytesAtom(data,0,data.length); + assertEquals(4008L, tba.getRecordType()); + } - @Test - void testTextA() { - TextBytesAtom tba = new TextBytesAtom(data,0,data.length); - String data_text = "This is the title on page 2"; - assertEquals(data_text, tba.getText()); - } + @Test + void testTextA() { + TextBytesAtom tba = new TextBytesAtom(data,0,data.length); + String data_text = "This is the title on page 2"; + assertEquals(data_text, tba.getText()); + } - @Test - void testTextB() { - TextBytesAtom tba = new TextBytesAtom(alt_data,0,alt_data.length); - assertEquals(alt_text, tba.getText()); - } + @Test + void testTextB() { + TextBytesAtom tba = new TextBytesAtom(alt_data,0,alt_data.length); + assertEquals(alt_text, tba.getText()); + } - @Test - void testChangeText() throws Exception { - TextBytesAtom tba = new TextBytesAtom(data,0,data.length); - tba.setText(alt_text.getBytes(StandardCharsets.ISO_8859_1)); + @Test + void testChangeText() throws Exception { + TextBytesAtom tba = new TextBytesAtom(data,0,data.length); + tba.setText(alt_text.getBytes(StandardCharsets.ISO_8859_1)); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - tba.writeOut(baos); - assertArrayEquals(alt_data, baos.toByteArray()); - } + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + tba.writeOut(baos); + assertArrayEquals(alt_data, baos.toByteArray()); + } - @Test - void testWrite() throws Exception { - TextBytesAtom tba = new TextBytesAtom(data,0,data.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - tba.writeOut(baos); - assertArrayEquals(data, baos.toByteArray()); - } + @Test + void testWrite() throws Exception { + TextBytesAtom tba = new TextBytesAtom(data,0,data.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + tba.writeOut(baos); + assertArrayEquals(data, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextCharsAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextCharsAtom.java index 382719cdfc..d2357a8fdc 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextCharsAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextCharsAtom.java @@ -28,62 +28,62 @@ import org.junit.jupiter.api.Test; * Tests that TextCharsAtom works properly */ public final class TestTextCharsAtom { - // From a real file - private final byte[] data = new byte[] { 0, 0, 0xA0-256, 0x0f, 0x08, 0, 0, 0, - 0x54, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00 }; - private final String data_text = "This"; - private final byte[] alt_data = new byte[] { 0, 0, 0xA0-256, 0x0F, 0x0a, 0, 0, 0, - 0x54, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0xa3-256, 0x01 }; - private final String alt_text = "This\u01A3"; - - @Test + // From a real file + private final byte[] data = new byte[] { 0, 0, 0xA0-256, 0x0f, 0x08, 0, 0, 0, + 0x54, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00 }; + private final String data_text = "This"; + private final byte[] alt_data = new byte[] { 0, 0, 0xA0-256, 0x0F, 0x0a, 0, 0, 0, + 0x54, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0xa3-256, 0x01 }; + private final String alt_text = "This\u01A3"; + + @Test void testRecordType() { - TextCharsAtom tca = new TextCharsAtom(data,0,data.length); - assertEquals(4000L, tca.getRecordType()); - } - - @Test - void testTextA() { - TextCharsAtom tca = new TextCharsAtom(data,0,data.length); - assertEquals(data_text, tca.getText()); - } - - @Test - void testTextB() { - TextCharsAtom tca = new TextCharsAtom(alt_data,0,alt_data.length); - assertEquals(alt_text, tca.getText()); - } - - @Test - void testChangeText() throws Exception { - TextCharsAtom tca = new TextCharsAtom(data,0,data.length); - tca.setText(alt_text); - - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - tca.writeOut(baos); - assertArrayEquals(alt_data, baos.toByteArray()); - } - - @Test - void testWrite() throws Exception { - TextCharsAtom tca = new TextCharsAtom(data,0,data.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - tca.writeOut(baos); - assertArrayEquals(data, baos.toByteArray()); - } - - @Test - void testCreateNew() throws Exception { - TextCharsAtom tca = new TextCharsAtom(); - assertEquals(0, tca.getText().length()); - - tca.setText(data_text); - assertEquals(data_text, tca.getText()); - - // Check it's now like data - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - tca.writeOut(baos); - assertArrayEquals(data, baos.toByteArray()); - } + TextCharsAtom tca = new TextCharsAtom(data,0,data.length); + assertEquals(4000L, tca.getRecordType()); + } + + @Test + void testTextA() { + TextCharsAtom tca = new TextCharsAtom(data,0,data.length); + assertEquals(data_text, tca.getText()); + } + + @Test + void testTextB() { + TextCharsAtom tca = new TextCharsAtom(alt_data,0,alt_data.length); + assertEquals(alt_text, tca.getText()); + } + + @Test + void testChangeText() throws Exception { + TextCharsAtom tca = new TextCharsAtom(data,0,data.length); + tca.setText(alt_text); + + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + tca.writeOut(baos); + assertArrayEquals(alt_data, baos.toByteArray()); + } + + @Test + void testWrite() throws Exception { + TextCharsAtom tca = new TextCharsAtom(data,0,data.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + tca.writeOut(baos); + assertArrayEquals(data, baos.toByteArray()); + } + + @Test + void testCreateNew() throws Exception { + TextCharsAtom tca = new TextCharsAtom(); + assertEquals(0, tca.getText().length()); + + tca.setText(data_text); + assertEquals(data_text, tca.getText()); + + // Check it's now like data + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + tca.writeOut(baos); + assertArrayEquals(data, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextHeaderAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextHeaderAtom.java index 6eddf527af..22bce9375b 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextHeaderAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextHeaderAtom.java @@ -29,32 +29,32 @@ import org.junit.jupiter.api.Test; * Tests that TextHeaderAtom works properly */ public final class TestTextHeaderAtom { - // From a real file - private final byte[] notes_data = { 0, 0, 0x9f-256, 0x0f, 4, 0, 0, 0, 2, 0, 0, 0 }; - private final byte[] title_data = { 0, 0, 0x9f-256, 0x0f, 4, 0, 0, 0, 0, 0, 0, 0 }; - private final byte[] body_data = { 0, 0, 0x9f-256, 0x0f, 4, 0, 0, 0, 1, 0, 0, 0 }; - - @Test - void testRecordType() { - TextHeaderAtom tha = new TextHeaderAtom(notes_data,0,12); - assertEquals(3999L, tha.getRecordType()); - } - - @Test - void testTypes() { - TextHeaderAtom n_tha = new TextHeaderAtom(notes_data,0,12); - TextHeaderAtom t_tha = new TextHeaderAtom(title_data,0,12); - TextHeaderAtom b_tha = new TextHeaderAtom(body_data,0,12); - assertEquals(TextPlaceholder.NOTES.nativeId, n_tha.getTextType()); - assertEquals(TextPlaceholder.TITLE.nativeId, t_tha.getTextType()); - assertEquals(TextPlaceholder.BODY.nativeId, b_tha.getTextType()); - } - - @Test - void testWrite() throws Exception { - TextHeaderAtom tha = new TextHeaderAtom(notes_data,0,12); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - tha.writeOut(baos); - assertArrayEquals(notes_data, baos.toByteArray()); - } + // From a real file + private final byte[] notes_data = { 0, 0, 0x9f-256, 0x0f, 4, 0, 0, 0, 2, 0, 0, 0 }; + private final byte[] title_data = { 0, 0, 0x9f-256, 0x0f, 4, 0, 0, 0, 0, 0, 0, 0 }; + private final byte[] body_data = { 0, 0, 0x9f-256, 0x0f, 4, 0, 0, 0, 1, 0, 0, 0 }; + + @Test + void testRecordType() { + TextHeaderAtom tha = new TextHeaderAtom(notes_data,0,12); + assertEquals(3999L, tha.getRecordType()); + } + + @Test + void testTypes() { + TextHeaderAtom n_tha = new TextHeaderAtom(notes_data,0,12); + TextHeaderAtom t_tha = new TextHeaderAtom(title_data,0,12); + TextHeaderAtom b_tha = new TextHeaderAtom(body_data,0,12); + assertEquals(TextPlaceholder.NOTES.nativeId, n_tha.getTextType()); + assertEquals(TextPlaceholder.TITLE.nativeId, t_tha.getTextType()); + assertEquals(TextPlaceholder.BODY.nativeId, b_tha.getTextType()); + } + + @Test + void testWrite() throws Exception { + TextHeaderAtom tha = new TextHeaderAtom(notes_data,0,12); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + tha.writeOut(baos); + assertArrayEquals(notes_data, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextRulerAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextRulerAtom.java index a24402ec2a..2a64d4fc21 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextRulerAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextRulerAtom.java @@ -29,53 +29,53 @@ import org.junit.jupiter.api.Test; public final class TestTextRulerAtom { - //from a real file - private final byte[] data_1 = new byte[] { - 0x00, 0x00, (byte)0xA6, 0x0F, 0x18, 0x00, 0x00, 0x00, - (byte)0xF8, 0x1F, 0x00, 0x00, 0x75, 0x00, (byte)0xE2, 0x00, 0x59, - 0x01, (byte)0xC3, 0x01, 0x1A, 0x03, (byte)0x87, 0x03, (byte)0xF8, - 0x03, 0x69, 0x04, (byte)0xF6, 0x05, (byte)0xF6, 0x05 - }; - - private final byte[] data_2 = new byte[] { - 0x00, 0x00, (byte)0xA6, 0x0F, 0x0A, 0x00, 0x00, 0x00, - 0x08, 0x03, 0x00, 0x00, (byte)0xF9, 0x00, 0x41, 0x01, 0x41, 0x01 - }; - - @Test - void testReadRuler() { - TextRulerAtom ruler = new TextRulerAtom(data_1, 0, data_1.length); - assertEquals(ruler.getNumberOfLevels(), 0); - assertEquals(ruler.getDefaultTabSize(), 0); - - List<HSLFTabStop> tabStops = ruler.getTabStops(); - assertNotNull(tabStops); - - Integer[] textOffsets = ruler.getTextOffsets(); - assertArrayEquals(new Integer[]{117, 345, 794, 1016, 1526}, textOffsets); - - Integer[] bulletOffsets = ruler.getBulletOffsets(); - assertArrayEquals(new Integer[]{226, 451, 903, 1129, 1526}, bulletOffsets); - } + //from a real file + private final byte[] data_1 = new byte[] { + 0x00, 0x00, (byte)0xA6, 0x0F, 0x18, 0x00, 0x00, 0x00, + (byte)0xF8, 0x1F, 0x00, 0x00, 0x75, 0x00, (byte)0xE2, 0x00, 0x59, + 0x01, (byte)0xC3, 0x01, 0x1A, 0x03, (byte)0x87, 0x03, (byte)0xF8, + 0x03, 0x69, 0x04, (byte)0xF6, 0x05, (byte)0xF6, 0x05 + }; + + private final byte[] data_2 = new byte[] { + 0x00, 0x00, (byte)0xA6, 0x0F, 0x0A, 0x00, 0x00, 0x00, + 0x08, 0x03, 0x00, 0x00, (byte)0xF9, 0x00, 0x41, 0x01, 0x41, 0x01 + }; @Test - void testWriteRuler() throws Exception { - TextRulerAtom ruler = new TextRulerAtom(data_1, 0, data_1.length); - UnsynchronizedByteArrayOutputStream out = new UnsynchronizedByteArrayOutputStream(); - ruler.writeOut(out); + void testReadRuler() { + TextRulerAtom ruler = new TextRulerAtom(data_1, 0, data_1.length); + assertEquals(ruler.getNumberOfLevels(), 0); + assertEquals(ruler.getDefaultTabSize(), 0); - byte[] result = out.toByteArray(); - assertArrayEquals(result, data_1); - } + List<HSLFTabStop> tabStops = ruler.getTabStops(); + assertNotNull(tabStops); + + Integer[] textOffsets = ruler.getTextOffsets(); + assertArrayEquals(new Integer[]{117, 345, 794, 1016, 1526}, textOffsets); + + Integer[] bulletOffsets = ruler.getBulletOffsets(); + assertArrayEquals(new Integer[]{226, 451, 903, 1129, 1526}, bulletOffsets); + } + + @Test + void testWriteRuler() throws Exception { + TextRulerAtom ruler = new TextRulerAtom(data_1, 0, data_1.length); + UnsynchronizedByteArrayOutputStream out = new UnsynchronizedByteArrayOutputStream(); + ruler.writeOut(out); + + byte[] result = out.toByteArray(); + assertArrayEquals(result, data_1); + } @Test - void testRead2() throws Exception { - TextRulerAtom ruler = TextRulerAtom.getParagraphInstance(); - ruler.setParagraphIndent((short)249, (short)321); - UnsynchronizedByteArrayOutputStream out = new UnsynchronizedByteArrayOutputStream(); - ruler.writeOut(out); - - byte[] result = out.toByteArray(); - assertArrayEquals(data_2, result); - } + void testRead2() throws Exception { + TextRulerAtom ruler = TextRulerAtom.getParagraphInstance(); + ruler.setParagraphIndent((short)249, (short)321); + UnsynchronizedByteArrayOutputStream out = new UnsynchronizedByteArrayOutputStream(); + ruler.writeOut(out); + + byte[] result = out.toByteArray(); + assertArrayEquals(data_2, result); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextSpecInfoAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextSpecInfoAtom.java index 93e8b5e420..c3cd26d1ce 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextSpecInfoAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTextSpecInfoAtom.java @@ -56,7 +56,7 @@ public final class TestTextSpecInfoAtom { UnsynchronizedByteArrayOutputStream out = new UnsynchronizedByteArrayOutputStream(); spec.writeOut(out); assertArrayEquals(data_1, out.toByteArray()); - } + } @Test void testReset() throws Exception { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTxInteractiveInfoAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTxInteractiveInfoAtom.java index 601baf0dc6..4671e7a8aa 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTxInteractiveInfoAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestTxInteractiveInfoAtom.java @@ -28,67 +28,67 @@ import org.junit.jupiter.api.Test; * Tests that TxInteractiveInfoAtom works properly. */ public final class TestTxInteractiveInfoAtom { - // From WithLinks.ppt - private final byte[] data_a = { - 0, 0, (byte)0xDF, 0x0F, 0x08, 0, 0, 0, - 0x19, 0, 0, 0, 0x38, 0, 0, 0 - }; - - private final byte[] data_b = { - 0, 0, (byte)0xDF, 0x0F, 0x08, 0, 0, 0, - 0x39, 0, 0, 0, 0x4E, 0, 0, 0 - }; - - @Test - void testRead() { - TxInteractiveInfoAtom ia1 = new TxInteractiveInfoAtom(data_a, 0, data_a.length); - - assertEquals(4063, ia1.getRecordType()); - assertEquals(25, ia1.getStartIndex()); - assertEquals(56, ia1.getEndIndex()); - - TxInteractiveInfoAtom ia2 = new TxInteractiveInfoAtom(data_b, 0, data_b.length); - - assertEquals(4063, ia2.getRecordType()); - assertEquals(57, ia2.getStartIndex()); - assertEquals(78, ia2.getEndIndex()); - } - - @Test - void testWrite() throws Exception { - TxInteractiveInfoAtom atom = new TxInteractiveInfoAtom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - atom.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } - - // Create A from scratch - @Test - void testCreate() throws Exception { - TxInteractiveInfoAtom ia = new TxInteractiveInfoAtom(); - - // Set values - ia.setStartIndex(25); - ia.setEndIndex(56); - - // Check it's now the same as a - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ia.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } - - // Try to turn a into b - @Test - void testChange() throws Exception { - TxInteractiveInfoAtom ia = new TxInteractiveInfoAtom(data_a, 0, data_a.length); - - // Change the number - ia.setStartIndex(57); - ia.setEndIndex(78); - - // Check bytes are now the same - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - ia.writeOut(baos); - assertArrayEquals(data_b, baos.toByteArray()); - } + // From WithLinks.ppt + private final byte[] data_a = { + 0, 0, (byte)0xDF, 0x0F, 0x08, 0, 0, 0, + 0x19, 0, 0, 0, 0x38, 0, 0, 0 + }; + + private final byte[] data_b = { + 0, 0, (byte)0xDF, 0x0F, 0x08, 0, 0, 0, + 0x39, 0, 0, 0, 0x4E, 0, 0, 0 + }; + + @Test + void testRead() { + TxInteractiveInfoAtom ia1 = new TxInteractiveInfoAtom(data_a, 0, data_a.length); + + assertEquals(4063, ia1.getRecordType()); + assertEquals(25, ia1.getStartIndex()); + assertEquals(56, ia1.getEndIndex()); + + TxInteractiveInfoAtom ia2 = new TxInteractiveInfoAtom(data_b, 0, data_b.length); + + assertEquals(4063, ia2.getRecordType()); + assertEquals(57, ia2.getStartIndex()); + assertEquals(78, ia2.getEndIndex()); + } + + @Test + void testWrite() throws Exception { + TxInteractiveInfoAtom atom = new TxInteractiveInfoAtom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + atom.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } + + // Create A from scratch + @Test + void testCreate() throws Exception { + TxInteractiveInfoAtom ia = new TxInteractiveInfoAtom(); + + // Set values + ia.setStartIndex(25); + ia.setEndIndex(56); + + // Check it's now the same as a + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ia.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } + + // Try to turn a into b + @Test + void testChange() throws Exception { + TxInteractiveInfoAtom ia = new TxInteractiveInfoAtom(data_a, 0, data_a.length); + + // Change the number + ia.setStartIndex(57); + ia.setEndIndex(78); + + // Check bytes are now the same + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + ia.writeOut(baos); + assertArrayEquals(data_b, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestUserEditAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestUserEditAtom.java index 42b34157d9..a7defb0e38 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestUserEditAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestUserEditAtom.java @@ -28,36 +28,36 @@ import org.junit.jupiter.api.Test; * Tests that UserEditAtom works properly */ public final class TestUserEditAtom { - // From a real file - private final byte[] data_a = new byte[] { 0, 0, 0xF5-256, 0x0F, 0x1C, 0, 0, 0, - 0, 1, 0, 0, 0xD9-256, 18, 0, 3, - 0, 0, 0, 0, 0, 0x18, 0, 0, 1, 0, 0, 0, - 5, 0, 0, 0, 1, 0, 0xF6-256, 77 }; - - @Test - void testRecordType() { - UserEditAtom uea = new UserEditAtom(data_a, 0, data_a.length); - assertEquals(4085L, uea.getRecordType()); - } - - @Test - void testFlags() { - UserEditAtom uea = new UserEditAtom(data_a, 0, data_a.length); - - assertEquals(256, uea.getLastViewedSlideID() ); - //assertEquals(0x030018D9, uea.getPPTVersion() ); - assertEquals(0, uea.getLastUserEditAtomOffset() ); - assertEquals(0x1800, uea.getPersistPointersOffset() ); - assertEquals(1, uea.getDocPersistRef() ); - assertEquals(5, uea.getMaxPersistWritten() ); - assertEquals((short)1, uea.getLastViewType() ); - } - - @Test - void testWrite() throws Exception { - UserEditAtom uea = new UserEditAtom(data_a, 0, data_a.length); - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - uea.writeOut(baos); - assertArrayEquals(data_a, baos.toByteArray()); - } + // From a real file + private final byte[] data_a = new byte[] { 0, 0, 0xF5-256, 0x0F, 0x1C, 0, 0, 0, + 0, 1, 0, 0, 0xD9-256, 18, 0, 3, + 0, 0, 0, 0, 0, 0x18, 0, 0, 1, 0, 0, 0, + 5, 0, 0, 0, 1, 0, 0xF6-256, 77 }; + + @Test + void testRecordType() { + UserEditAtom uea = new UserEditAtom(data_a, 0, data_a.length); + assertEquals(4085L, uea.getRecordType()); + } + + @Test + void testFlags() { + UserEditAtom uea = new UserEditAtom(data_a, 0, data_a.length); + + assertEquals(256, uea.getLastViewedSlideID() ); + //assertEquals(0x030018D9, uea.getPPTVersion() ); + assertEquals(0, uea.getLastUserEditAtomOffset() ); + assertEquals(0x1800, uea.getPersistPointersOffset() ); + assertEquals(1, uea.getDocPersistRef() ); + assertEquals(5, uea.getMaxPersistWritten() ); + assertEquals((short)1, uea.getLastViewType() ); + } + + @Test + void testWrite() throws Exception { + UserEditAtom uea = new UserEditAtom(data_a, 0, data_a.length); + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + uea.writeOut(baos); + assertArrayEquals(data_a, baos.toByteArray()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestBugs.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestBugs.java index 17ddfa4a8a..6e8c8b5e92 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestBugs.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestBugs.java @@ -381,7 +381,7 @@ public final class TestBugs { */ @Test void bug41711() throws IOException { - // New file is fine + // New file is fine open("SampleShow.ppt").close(); // PowerPoint 95 gives an old format exception diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestCounts.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestCounts.java index d4dce2b13f..9f6c4d49ff 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestCounts.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestCounts.java @@ -31,49 +31,49 @@ import org.junit.jupiter.api.Test; */ public final class TestCounts { @Test - void testSheetsCount() throws IOException { - HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); + void testSheetsCount() throws IOException { + HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); - List<HSLFSlide> slides = ppt.getSlides(); - // Two sheets - master sheet is separate - assertEquals(2, slides.size()); + List<HSLFSlide> slides = ppt.getSlides(); + // Two sheets - master sheet is separate + assertEquals(2, slides.size()); - // They are slides 1+2 - assertEquals(1, slides.get(0).getSlideNumber()); - assertEquals(2, slides.get(1).getSlideNumber()); + // They are slides 1+2 + assertEquals(1, slides.get(0).getSlideNumber()); + assertEquals(2, slides.get(1).getSlideNumber()); - // The ref IDs are 4 and 6 - assertEquals(4, slides.get(0)._getSheetRefId()); - assertEquals(6, slides.get(1)._getSheetRefId()); + // The ref IDs are 4 and 6 + assertEquals(4, slides.get(0)._getSheetRefId()); + assertEquals(6, slides.get(1)._getSheetRefId()); - // These are slides 1+2 -> 256+257 - assertEquals(256, slides.get(0)._getSheetNumber()); - assertEquals(257, slides.get(1)._getSheetNumber()); + // These are slides 1+2 -> 256+257 + assertEquals(256, slides.get(0)._getSheetNumber()); + assertEquals(257, slides.get(1)._getSheetNumber()); - ppt.close(); - } + ppt.close(); + } @Test void testNotesCount() throws IOException { HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); - List<HSLFNotes> notes = ppt.getNotes(); - // Two sheets -> two notes - // Note: there are also notes on the slide master - //assertEquals(3, notes.length); // When we do slide masters - assertEquals(2, notes.size()); + List<HSLFNotes> notes = ppt.getNotes(); + // Two sheets -> two notes + // Note: there are also notes on the slide master + //assertEquals(3, notes.length); // When we do slide masters + assertEquals(2, notes.size()); - // First is for master - //assertEquals(-2147483648, notes.get(0)._getSheetNumber()); // When we do slide masters + // First is for master + //assertEquals(-2147483648, notes.get(0)._getSheetNumber()); // When we do slide masters - // Next two are for the two slides - assertEquals(256, notes.get(0)._getSheetNumber()); - assertEquals(257, notes.get(1)._getSheetNumber()); + // Next two are for the two slides + assertEquals(256, notes.get(0)._getSheetNumber()); + assertEquals(257, notes.get(1)._getSheetNumber()); - // They happen to go between the two slides in Ref terms - assertEquals(5, notes.get(0)._getSheetRefId()); - assertEquals(7, notes.get(1)._getSheetRefId()); + // They happen to go between the two slides in Ref terms + assertEquals(5, notes.get(0)._getSheetRefId()); + assertEquals(7, notes.get(1)._getSheetRefId()); - ppt.close(); - } + ppt.close(); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestMostRecentRecords.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestMostRecentRecords.java index d96201b89f..17c5b3728c 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestMostRecentRecords.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestMostRecentRecords.java @@ -28,73 +28,73 @@ import org.junit.jupiter.api.Test; * Tests that SlideShow finds the right records as its most recent ones */ public final class TestMostRecentRecords { - // HSLFSlideShow primed on the test data - private HSLFSlideShowImpl hss; - // SlideShow primed on the test data - private HSLFSlideShow ss; - - @BeforeEach - void setup() throws Exception { - POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new HSLFSlideShow(hss); - } - - @Test - void testCount() { - // Most recent core records - org.apache.poi.hslf.record.Record[] mrcr = ss.getMostRecentCoreRecords(); - - // Master sheet + master notes + 2 slides + 2 notes + document - assertEquals(7, mrcr.length); - } - - @Test - void testRightRecordTypes() { - // Most recent core records - org.apache.poi.hslf.record.Record[] mrcr = ss.getMostRecentCoreRecords(); - - // Document - assertEquals(1000, mrcr[0].getRecordType()); - // Notes of master - assertEquals(1008, mrcr[1].getRecordType()); - // Master - assertEquals(1016, mrcr[2].getRecordType()); - - // Slide - assertEquals(1006, mrcr[3].getRecordType()); - // Notes - assertEquals(1008, mrcr[4].getRecordType()); - // Slide - assertEquals(1006, mrcr[5].getRecordType()); - // Notes - assertEquals(1008, mrcr[6].getRecordType()); - } - - @Test - void testCorrectRecords() { - // Most recent core records - org.apache.poi.hslf.record.Record[] mrcr = ss.getMostRecentCoreRecords(); - - // All records - org.apache.poi.hslf.record.Record[] allr = hss.getRecords(); - - // Ensure they are the right (latest) version of each - - // Document - late version - assertEquals(allr[12], mrcr[0]); - // Notes of master - unchanged - assertEquals(allr[2], mrcr[1]); - // Master - unchanged - assertEquals(allr[1], mrcr[2]); - - // Slide - added at start - assertEquals(allr[3], mrcr[3]); - // Notes - added at start - assertEquals(allr[4], mrcr[4]); - // Slide - added later and then changed - assertEquals(allr[13], mrcr[5]); - // Notes - added later but not changed - assertEquals(allr[9], mrcr[6]); - } + // HSLFSlideShow primed on the test data + private HSLFSlideShowImpl hss; + // SlideShow primed on the test data + private HSLFSlideShow ss; + + @BeforeEach + void setup() throws Exception { + POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); + hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); + } + + @Test + void testCount() { + // Most recent core records + org.apache.poi.hslf.record.Record[] mrcr = ss.getMostRecentCoreRecords(); + + // Master sheet + master notes + 2 slides + 2 notes + document + assertEquals(7, mrcr.length); + } + + @Test + void testRightRecordTypes() { + // Most recent core records + org.apache.poi.hslf.record.Record[] mrcr = ss.getMostRecentCoreRecords(); + + // Document + assertEquals(1000, mrcr[0].getRecordType()); + // Notes of master + assertEquals(1008, mrcr[1].getRecordType()); + // Master + assertEquals(1016, mrcr[2].getRecordType()); + + // Slide + assertEquals(1006, mrcr[3].getRecordType()); + // Notes + assertEquals(1008, mrcr[4].getRecordType()); + // Slide + assertEquals(1006, mrcr[5].getRecordType()); + // Notes + assertEquals(1008, mrcr[6].getRecordType()); + } + + @Test + void testCorrectRecords() { + // Most recent core records + org.apache.poi.hslf.record.Record[] mrcr = ss.getMostRecentCoreRecords(); + + // All records + org.apache.poi.hslf.record.Record[] allr = hss.getRecords(); + + // Ensure they are the right (latest) version of each + + // Document - late version + assertEquals(allr[12], mrcr[0]); + // Notes of master - unchanged + assertEquals(allr[2], mrcr[1]); + // Master - unchanged + assertEquals(allr[1], mrcr[2]); + + // Slide - added at start + assertEquals(allr[3], mrcr[3]); + // Notes - added at start + assertEquals(allr[4], mrcr[4]); + // Slide - added later and then changed + assertEquals(allr[13], mrcr[5]); + // Notes - added later but not changed + assertEquals(allr[9], mrcr[6]); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNotesText.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNotesText.java index 69863e5685..6ca766172e 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNotesText.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNotesText.java @@ -28,31 +28,31 @@ import org.junit.jupiter.api.Test; * Tests that SlideShow returns MetaSheets which have the right text in them */ public final class TestNotesText { - // SlideShow primed on the test data - private HSLFSlideShow ss; - - @BeforeEach - void setup() throws Exception { - POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new HSLFSlideShow(hss); - } - - @Test - void testNotesOne() { - HSLFNotes notes = ss.getNotes().get(0); - String[] expectText = {"These are the notes for page 1"}; - assertArrayEquals(expectText, toStrings(notes)); - } - - @Test - void testNotesTwo() { - HSLFNotes notes = ss.getNotes().get(1); - String[] expectText = {"These are the notes on page two, again lacking formatting"}; - assertArrayEquals(expectText, toStrings(notes)); - } - - private static String[] toStrings(HSLFNotes notes) { - return notes.getTextParagraphs().stream().map(HSLFTextParagraph::getRawText).toArray(String[]::new); - } + // SlideShow primed on the test data + private HSLFSlideShow ss; + + @BeforeEach + void setup() throws Exception { + POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); + } + + @Test + void testNotesOne() { + HSLFNotes notes = ss.getNotes().get(0); + String[] expectText = {"These are the notes for page 1"}; + assertArrayEquals(expectText, toStrings(notes)); + } + + @Test + void testNotesTwo() { + HSLFNotes notes = ss.getNotes().get(1); + String[] expectText = {"These are the notes on page two, again lacking formatting"}; + assertArrayEquals(expectText, toStrings(notes)); + } + + private static String[] toStrings(HSLFNotes notes) { + return notes.getTextParagraphs().stream().map(HSLFTextParagraph::getRawText).toArray(String[]::new); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList.java index e39ef463f9..398f6e5bc0 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList.java @@ -45,96 +45,96 @@ public final class TestNumberedList { @Test void testNumberedList() throws Exception { - HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers.ppt")); - final List<HSLFSlide> slides = ppt.getSlides(); - assertEquals(2, slides.size()); - checkSlide0(slides.get(0)); - checkSlide1(slides.get(1)); - ppt.close(); - } + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers.ppt")); + final List<HSLFSlide> slides = ppt.getSlides(); + assertEquals(2, slides.size()); + checkSlide0(slides.get(0)); + checkSlide1(slides.get(1)); + ppt.close(); + } private void checkSlide0(final HSLFSlide s) { - final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); - assertNotNull(numberedListArray); - assertEquals(1, numberedListArray.length);//Just one text box here - final StyleTextProp9Atom numberedListInfo = numberedListArray[0]; - assertNotNull(numberedListInfo); - final TextPFException9[] autoNumbers = numberedListInfo.getAutoNumberTypes(); - assertNotNull(autoNumbers); - assertEquals(4, autoNumbers.length); + final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); + assertNotNull(numberedListArray); + assertEquals(1, numberedListArray.length);//Just one text box here + final StyleTextProp9Atom numberedListInfo = numberedListArray[0]; + assertNotNull(numberedListInfo); + final TextPFException9[] autoNumbers = numberedListInfo.getAutoNumberTypes(); + assertNotNull(autoNumbers); + assertEquals(4, autoNumbers.length); assertEquals(4, (short) autoNumbers[0].getAutoNumberStartNumber()); - assertNull(autoNumbers[1].getAutoNumberStartNumber()); + assertNull(autoNumbers[1].getAutoNumberStartNumber()); assertEquals(3, (short) autoNumbers[2].getAutoNumberStartNumber()); assertSame(AutoNumberingScheme.arabicPeriod, autoNumbers[0].getAutoNumberScheme()); - assertNull(autoNumbers[1].getAutoNumberScheme()); + assertNull(autoNumbers[1].getAutoNumberScheme()); assertSame(AutoNumberingScheme.alphaLcParenRight, autoNumbers[2].getAutoNumberScheme()); - List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); - assertEquals(2, textParass.size()); - - List<HSLFTextParagraph> textParas = textParass.get(0); - assertEquals("titTe", HSLFTextParagraph.getRawText(textParas)); - assertEquals(1, textParas.size()); - assertFalse(textParas.get(0).isBullet()); - - String expected = - "This is a text placeholder that \r" + - "follows the design pattern\r" + - "Just a test\rWithout any paragraph\r" + - "Second paragraph first line c) ;\r" + - "Second paragraph second line d) . \r"; - assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(1))); - - final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); - assertEquals(textParass.size(), styleAtoms.length); - final EscherTextboxWrapper wrapper = styleAtoms[1]; - final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); - final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); - assertEquals(60, textProps.get(0).getCharactersCovered()); - assertEquals(34, textProps.get(1).getCharactersCovered()); - assertEquals(68, textProps.get(2).getCharactersCovered()); - } + List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); + assertEquals(2, textParass.size()); + + List<HSLFTextParagraph> textParas = textParass.get(0); + assertEquals("titTe", HSLFTextParagraph.getRawText(textParas)); + assertEquals(1, textParas.size()); + assertFalse(textParas.get(0).isBullet()); + + String expected = + "This is a text placeholder that \r" + + "follows the design pattern\r" + + "Just a test\rWithout any paragraph\r" + + "Second paragraph first line c) ;\r" + + "Second paragraph second line d) . \r"; + assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(1))); + + final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); + assertEquals(textParass.size(), styleAtoms.length); + final EscherTextboxWrapper wrapper = styleAtoms[1]; + final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); + final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); + assertEquals(60, textProps.get(0).getCharactersCovered()); + assertEquals(34, textProps.get(1).getCharactersCovered()); + assertEquals(68, textProps.get(2).getCharactersCovered()); + } private void checkSlide1(final HSLFSlide s) { - final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); - assertNotNull(numberedListArray); - assertEquals(1, numberedListArray.length);//Just one text box here - final StyleTextProp9Atom numberedListInfo = numberedListArray[0]; - assertNotNull(numberedListInfo); - final TextPFException9[] autoNumbers = numberedListInfo.getAutoNumberTypes(); - assertNotNull(autoNumbers); - assertEquals(4, autoNumbers.length); + final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); + assertNotNull(numberedListArray); + assertEquals(1, numberedListArray.length);//Just one text box here + final StyleTextProp9Atom numberedListInfo = numberedListArray[0]; + assertNotNull(numberedListInfo); + final TextPFException9[] autoNumbers = numberedListInfo.getAutoNumberTypes(); + assertNotNull(autoNumbers); + assertEquals(4, autoNumbers.length); assertEquals(9, (short) autoNumbers[0].getAutoNumberStartNumber()); - assertNull(autoNumbers[1].getAutoNumberStartNumber()); + assertNull(autoNumbers[1].getAutoNumberStartNumber()); assertEquals(3, (short) autoNumbers[2].getAutoNumberStartNumber()); assertSame(AutoNumberingScheme.arabicParenRight, autoNumbers[0].getAutoNumberScheme()); - assertNull(autoNumbers[1].getAutoNumberScheme()); + assertNull(autoNumbers[1].getAutoNumberScheme()); assertSame(AutoNumberingScheme.alphaUcPeriod, autoNumbers[2].getAutoNumberScheme()); - final List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); - assertEquals(2, textParass.size()); - - List<HSLFTextParagraph> textParas = textParass.get(0); - assertEquals("Second Slide Title", HSLFTextParagraph.getRawText(textParas)); - assertEquals(1, textParas.size()); - assertFalse(textParas.get(0).isBullet()); - - String expected = - "This is a text placeholder that \r" + - "follows the design pattern\r" + - "Just a test\rWithout any paragraph\r" + - "Second paragraph first line c) ;\r" + - "Second paragraph second line d) . \r"; - assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(1))); - - final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); - assertEquals(textParass.size(), styleAtoms.length); - final EscherTextboxWrapper wrapper = styleAtoms[1]; - final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); - final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); - - assertEquals(33, textProps.get(0).getCharactersCovered()); - assertEquals(61, textProps.get(1).getCharactersCovered()); - assertEquals(68, textProps.get(2).getCharactersCovered()); - } + final List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); + assertEquals(2, textParass.size()); + + List<HSLFTextParagraph> textParas = textParass.get(0); + assertEquals("Second Slide Title", HSLFTextParagraph.getRawText(textParas)); + assertEquals(1, textParas.size()); + assertFalse(textParas.get(0).isBullet()); + + String expected = + "This is a text placeholder that \r" + + "follows the design pattern\r" + + "Just a test\rWithout any paragraph\r" + + "Second paragraph first line c) ;\r" + + "Second paragraph second line d) . \r"; + assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(1))); + + final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); + assertEquals(textParass.size(), styleAtoms.length); + final EscherTextboxWrapper wrapper = styleAtoms[1]; + final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); + final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); + + assertEquals(33, textProps.get(0).getCharactersCovered()); + assertEquals(61, textProps.get(1).getCharactersCovered()); + assertEquals(68, textProps.get(2).getCharactersCovered()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList2.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList2.java index 6e49fd10d7..4ce43c380d 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList2.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList2.java @@ -47,88 +47,88 @@ public final class TestNumberedList2 { private static final POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); @Test - void testNumberedList() throws IOException { - try (HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers2.ppt"))) { - final List<HSLFSlide> slides = ppt.getSlides(); - assertEquals(2, slides.size()); - checkSlide0(slides.get(0)); - checkSlide1(slides.get(1)); - } + void testNumberedList() throws IOException { + try (HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers2.ppt"))) { + final List<HSLFSlide> slides = ppt.getSlides(); + assertEquals(2, slides.size()); + checkSlide0(slides.get(0)); + checkSlide1(slides.get(1)); + } } private void checkSlide0(final HSLFSlide s) { - final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); - assertNotNull(numberedListArray); - assertEquals(2, numberedListArray.length); - final StyleTextProp9Atom numberedListInfoForTextBox0 = numberedListArray[0]; - final StyleTextProp9Atom numberedListInfoForTextBox1 = numberedListArray[1]; - assertNotNull(numberedListInfoForTextBox0); - assertNotNull(numberedListInfoForTextBox1); - final TextPFException9[] autoNumbersOfTextBox0 = numberedListInfoForTextBox0.getAutoNumberTypes(); - assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox0[0].getfBulletHasAutoNumber()); - assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox0[0].getAutoNumberStartNumber());//Default value = 1 will be used + final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); + assertNotNull(numberedListArray); + assertEquals(2, numberedListArray.length); + final StyleTextProp9Atom numberedListInfoForTextBox0 = numberedListArray[0]; + final StyleTextProp9Atom numberedListInfoForTextBox1 = numberedListArray[1]; + assertNotNull(numberedListInfoForTextBox0); + assertNotNull(numberedListInfoForTextBox1); + final TextPFException9[] autoNumbersOfTextBox0 = numberedListInfoForTextBox0.getAutoNumberTypes(); + assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox0[0].getfBulletHasAutoNumber()); + assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox0[0].getAutoNumberStartNumber());//Default value = 1 will be used assertSame(AutoNumberingScheme.arabicPeriod, autoNumbersOfTextBox0[0].getAutoNumberScheme()); - final TextPFException9[] autoNumbersOfTextBox1 = numberedListInfoForTextBox1.getAutoNumberTypes(); - assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox1[0].getfBulletHasAutoNumber()); - assertEquals(Short.valueOf((short)6), autoNumbersOfTextBox1[0].getAutoNumberStartNumber());//Default value = 1 will be used + final TextPFException9[] autoNumbersOfTextBox1 = numberedListInfoForTextBox1.getAutoNumberTypes(); + assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox1[0].getfBulletHasAutoNumber()); + assertEquals(Short.valueOf((short)6), autoNumbersOfTextBox1[0].getAutoNumberStartNumber());//Default value = 1 will be used assertSame(AutoNumberingScheme.arabicPeriod, autoNumbersOfTextBox1[0].getAutoNumberScheme()); - List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); - assertEquals(2, textParass.size()); + List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); + assertEquals(2, textParass.size()); - List<HSLFTextParagraph> textParas = textParass.get(0); - assertEquals("List Item One\rList Item Two\rList Item Three", HSLFTextParagraph.getRawText(textParas)); - assertEquals(3, textParas.size()); - assertTrue(textParas.get(0).isBullet()); + List<HSLFTextParagraph> textParas = textParass.get(0); + assertEquals("List Item One\rList Item Two\rList Item Three", HSLFTextParagraph.getRawText(textParas)); + assertEquals(3, textParas.size()); + assertTrue(textParas.get(0).isBullet()); - String expected = - "A numbered list may start at any number \r" + - "This would be used as a continuation list on another page\r" + + String expected = + "A numbered list may start at any number \r" + + "This would be used as a continuation list on another page\r" + "This list should start with #6"; - assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(1))); - - final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); - assertEquals(textParass.size(), styleAtoms.length); - checkSingleRunWrapper(44, styleAtoms[0]); - checkSingleRunWrapper(130, styleAtoms[1]); - } - - private void checkSlide1(final HSLFSlide s) { - final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); - assertNotNull(numberedListArray); - assertEquals(1, numberedListArray.length); - final StyleTextProp9Atom numberedListInfoForTextBox = numberedListArray[0]; - assertNotNull(numberedListInfoForTextBox); - final TextPFException9[] autoNumbersOfTextBox = numberedListInfoForTextBox.getAutoNumberTypes(); - assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox[0].getfBulletHasAutoNumber()); - assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox[0].getAutoNumberStartNumber());//Default value = 1 will be used + assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(1))); + + final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); + assertEquals(textParass.size(), styleAtoms.length); + checkSingleRunWrapper(44, styleAtoms[0]); + checkSingleRunWrapper(130, styleAtoms[1]); + } + + private void checkSlide1(final HSLFSlide s) { + final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); + assertNotNull(numberedListArray); + assertEquals(1, numberedListArray.length); + final StyleTextProp9Atom numberedListInfoForTextBox = numberedListArray[0]; + assertNotNull(numberedListInfoForTextBox); + final TextPFException9[] autoNumbersOfTextBox = numberedListInfoForTextBox.getAutoNumberTypes(); + assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox[0].getfBulletHasAutoNumber()); + assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox[0].getAutoNumberStartNumber());//Default value = 1 will be used assertSame(AutoNumberingScheme.arabicPeriod, autoNumbersOfTextBox[0].getAutoNumberScheme()); - List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); - assertEquals(3, textParass.size()); - - List<HSLFTextParagraph> textParas = textParass.get(0); - assertEquals("Bulleted list\rMore bullets", HSLFTextParagraph.getRawText(textParas)); - assertEquals(2, textParas.size()); - assertTrue(textParas.get(0).isBullet()); - - String expected = "Numbered list between two bulleted lists\rSecond numbered list item"; - assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(1))); - expected = "Second bulleted list \u2013 should appear after numbered list\rMore bullets"; - assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(2))); - - final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); - assertEquals(textParass.size(), styleAtoms.length); - checkSingleRunWrapper(27, styleAtoms[0]); - checkSingleRunWrapper(67, styleAtoms[1]); - checkSingleRunWrapper(70, styleAtoms[2]); - } - - private void checkSingleRunWrapper(final int exceptedLength, final EscherTextboxWrapper wrapper) { - final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); - final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); - assertEquals(1, textProps.size()); - assertEquals(exceptedLength, textProps.get(0).getCharactersCovered()); - } + List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); + assertEquals(3, textParass.size()); + + List<HSLFTextParagraph> textParas = textParass.get(0); + assertEquals("Bulleted list\rMore bullets", HSLFTextParagraph.getRawText(textParas)); + assertEquals(2, textParas.size()); + assertTrue(textParas.get(0).isBullet()); + + String expected = "Numbered list between two bulleted lists\rSecond numbered list item"; + assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(1))); + expected = "Second bulleted list \u2013 should appear after numbered list\rMore bullets"; + assertEquals(expected, HSLFTextParagraph.getRawText(textParass.get(2))); + + final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); + assertEquals(textParass.size(), styleAtoms.length); + checkSingleRunWrapper(27, styleAtoms[0]); + checkSingleRunWrapper(67, styleAtoms[1]); + checkSingleRunWrapper(70, styleAtoms[2]); + } + + private void checkSingleRunWrapper(final int exceptedLength, final EscherTextboxWrapper wrapper) { + final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); + final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); + assertEquals(1, textProps.size()); + assertEquals(exceptedLength, textProps.get(0).getCharactersCovered()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList3.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList3.java index 6475d51b5d..5cca1478cc 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList3.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestNumberedList3.java @@ -49,61 +49,61 @@ public final class TestNumberedList3 { @Test void testNumberedList() throws IOException { - try (HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers3.ppt"))) { - final List<HSLFSlide> slides = ppt.getSlides(); - assertEquals(1, slides.size()); - final HSLFSlide slide = slides.get(0); - checkSlide(slide); - } - } - private void checkSlide(final HSLFSlide s) { - final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); - assertNotNull(numberedListArray); - assertEquals(1, numberedListArray.length); - final StyleTextProp9Atom numberedListInfoForTextBox = numberedListArray[0]; - assertNotNull(numberedListInfoForTextBox); - final TextPFException9[] autoNumbersOfTextBox0 = numberedListInfoForTextBox.getAutoNumberTypes(); - assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox0[0].getfBulletHasAutoNumber()); - assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox0[0].getAutoNumberStartNumber());//Default value = 1 will be used + try (HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers3.ppt"))) { + final List<HSLFSlide> slides = ppt.getSlides(); + assertEquals(1, slides.size()); + final HSLFSlide slide = slides.get(0); + checkSlide(slide); + } + } + private void checkSlide(final HSLFSlide s) { + final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo(); + assertNotNull(numberedListArray); + assertEquals(1, numberedListArray.length); + final StyleTextProp9Atom numberedListInfoForTextBox = numberedListArray[0]; + assertNotNull(numberedListInfoForTextBox); + final TextPFException9[] autoNumbersOfTextBox0 = numberedListInfoForTextBox.getAutoNumberTypes(); + assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox0[0].getfBulletHasAutoNumber()); + assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox0[0].getAutoNumberStartNumber());//Default value = 1 will be used assertSame(AutoNumberingScheme.arabicPeriod, autoNumbersOfTextBox0[0].getAutoNumberScheme()); - final List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); - assertEquals(3, textParass.size()); - assertEquals("Bulleted list\rMore bullets\rNo bullets here", HSLFTextParagraph.getRawText(textParass.get(0))); - assertEquals("Numbered list between two bulleted lists\rSecond numbered list item", HSLFTextParagraph.getRawText(textParass.get(1))); - assertEquals("Second bulleted list \u2013 should appear after numbered list\rMore bullets", HSLFTextParagraph.getRawText(textParass.get(2))); - assertEquals(3, textParass.get(0).size()); - assertEquals(2, textParass.get(1).size()); - assertEquals(2, textParass.get(2).size()); - assertNull(textParass.get(0).get(0).getStyleTextProp9Atom()); - assertNotNull(textParass.get(1).get(0).getStyleTextProp9Atom()); - assertNull(textParass.get(2).get(0).getStyleTextProp9Atom()); - final TextPFException9[] autoNumbers = textParass.get(1).get(0).getStyleTextProp9Atom().getAutoNumberTypes(); - assertEquals(1, autoNumbers.length); - assertEquals(Short.valueOf((short)1), autoNumbers[0].getfBulletHasAutoNumber()); - assertEquals(Short.valueOf((short)1), autoNumbers[0].getAutoNumberStartNumber());//Default value = 1 will be used + final List<List<HSLFTextParagraph>> textParass = s.getTextParagraphs(); + assertEquals(3, textParass.size()); + assertEquals("Bulleted list\rMore bullets\rNo bullets here", HSLFTextParagraph.getRawText(textParass.get(0))); + assertEquals("Numbered list between two bulleted lists\rSecond numbered list item", HSLFTextParagraph.getRawText(textParass.get(1))); + assertEquals("Second bulleted list \u2013 should appear after numbered list\rMore bullets", HSLFTextParagraph.getRawText(textParass.get(2))); + assertEquals(3, textParass.get(0).size()); + assertEquals(2, textParass.get(1).size()); + assertEquals(2, textParass.get(2).size()); + assertNull(textParass.get(0).get(0).getStyleTextProp9Atom()); + assertNotNull(textParass.get(1).get(0).getStyleTextProp9Atom()); + assertNull(textParass.get(2).get(0).getStyleTextProp9Atom()); + final TextPFException9[] autoNumbers = textParass.get(1).get(0).getStyleTextProp9Atom().getAutoNumberTypes(); + assertEquals(1, autoNumbers.length); + assertEquals(Short.valueOf((short)1), autoNumbers[0].getfBulletHasAutoNumber()); + assertEquals(Short.valueOf((short)1), autoNumbers[0].getAutoNumberStartNumber());//Default value = 1 will be used assertSame(AutoNumberingScheme.arabicPeriod, autoNumbersOfTextBox0[0].getAutoNumberScheme()); - int chCovered = 0; - for (HSLFTextParagraph htp : textParass.get(1)) { - for (HSLFTextRun htr : htp.getTextRuns()) { - TextPropCollection textProp = htr.getCharacterStyle(); - chCovered += textProp.getCharactersCovered(); - } - } - assertEquals(67, chCovered); + int chCovered = 0; + for (HSLFTextParagraph htp : textParass.get(1)) { + for (HSLFTextRun htr : htp.getTextRuns()) { + TextPropCollection textProp = htr.getCharacterStyle(); + chCovered += textProp.getCharactersCovered(); + } + } + assertEquals(67, chCovered); - assertTrue(textParass.get(0).get(0).isBullet()); + assertTrue(textParass.get(0).get(0).isBullet()); - final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); - assertEquals(textParass.size(), styleAtoms.length); - checkSingleRunWrapper(43, styleAtoms[0]); - checkSingleRunWrapper(67, styleAtoms[1]); - } - private void checkSingleRunWrapper(final int exceptedLength, final EscherTextboxWrapper wrapper) { - final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); - final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); - assertEquals(1, textProps.size()); - assertEquals(exceptedLength, textProps.get(0).getCharactersCovered()); - } + final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers(); + assertEquals(textParass.size(), styleAtoms.length); + checkSingleRunWrapper(43, styleAtoms[0]); + checkSingleRunWrapper(67, styleAtoms[1]); + } + private void checkSingleRunWrapper(final int exceptedLength, final EscherTextboxWrapper wrapper) { + final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom(); + final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles(); + assertEquals(1, textProps.size()); + assertEquals(exceptedLength, textProps.get(0).getCharactersCovered()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestPictures.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestPictures.java index 65a2716711..918d844ec8 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestPictures.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestPictures.java @@ -228,13 +228,13 @@ public final class TestPictures { } } - /** - * Test that on a party corrupt powerpoint document, which has - * crazy pictures of type 0, we do our best. - */ + /** + * Test that on a party corrupt powerpoint document, which has + * crazy pictures of type 0, we do our best. + */ @Test - void testZeroPictureType() throws IOException { - try (HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("PictureTypeZero.ppt"))) { + void testZeroPictureType() throws IOException { + try (HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("PictureTypeZero.ppt"))) { // Should still have 2 real pictures assertEquals(2, hslf.getPictureData().size()); @@ -262,7 +262,7 @@ public final class TestPictures { assertTrue(pdata instanceof WMF); assertEquals(PictureType.WMF, pdata.getType()); } - } + } /** * YK: The test is disabled because the owner asked to delete the test file from POI svn. @@ -271,10 +271,10 @@ public final class TestPictures { @Test @Disabled("requires an internet connection to a 3rd party site") // As of 2017-06-20, the file still exists at the specified URL and the test passes. - void testZeroPictureLength() throws IOException { + void testZeroPictureLength() throws IOException { // take the data from www instead of test directory URL url = new URL("http://www.cs.sfu.ca/~anoop/courses/CMPT-882-Fall-2002/chris.ppt"); - HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(url.openStream()); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(url.openStream()); /* Assume that the file could retrieved... InputStream is; HSLFSlideShowImpl hslf; @@ -288,14 +288,14 @@ public final class TestPictures { } */ - // Should still have 2 real pictures - assertEquals(2, hslf.getPictureData().size()); - // Both are real pictures, both WMF - assertEquals(PictureType.WMF, hslf.getPictureData().get(0).getType()); - assertEquals(PictureType.WMF, hslf.getPictureData().get(1).getType()); + // Should still have 2 real pictures + assertEquals(2, hslf.getPictureData().size()); + // Both are real pictures, both WMF + assertEquals(PictureType.WMF, hslf.getPictureData().get(0).getType()); + assertEquals(PictureType.WMF, hslf.getPictureData().get(1).getType()); - // Now test what happens when we use the SlideShow interface - try (HSLFSlideShow ppt = new HSLFSlideShow(hslf)) { + // Now test what happens when we use the SlideShow interface + try (HSLFSlideShow ppt = new HSLFSlideShow(hslf)) { List<HSLFSlide> slides = ppt.getSlides(); List<HSLFPictureData> pictures = ppt.getPictureData(); assertEquals(27, slides.size()); diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestReOrderingSlides.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestReOrderingSlides.java index 0b9255050b..ad6a00b6e3 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestReOrderingSlides.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestReOrderingSlides.java @@ -31,268 +31,268 @@ import org.junit.jupiter.api.Test; * Tests that SlideShow can re-order slides properly */ public final class TestReOrderingSlides { - // A SlideShow with one slide - private HSLFSlideShowImpl hss_one; - private HSLFSlideShow ss_one; - - // A SlideShow with two slides - private HSLFSlideShowImpl hss_two; - private HSLFSlideShow ss_two; - - // A SlideShow with three slides - private HSLFSlideShowImpl hss_three; - private HSLFSlideShow ss_three; - - /** - * Create/open the slideshows - */ - @BeforeEach - void setUp() throws Exception { + // A SlideShow with one slide + private HSLFSlideShowImpl hss_one; + private HSLFSlideShow ss_one; + + // A SlideShow with two slides + private HSLFSlideShowImpl hss_two; + private HSLFSlideShow ss_two; + + // A SlideShow with three slides + private HSLFSlideShowImpl hss_three; + private HSLFSlideShow ss_three; + + /** + * Create/open the slideshows + */ + @BeforeEach + void setUp() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - hss_one = new HSLFSlideShowImpl(slTests.openResourceAsStream("Single_Coloured_Page.ppt")); - ss_one = new HSLFSlideShow(hss_one); + hss_one = new HSLFSlideShowImpl(slTests.openResourceAsStream("Single_Coloured_Page.ppt")); + ss_one = new HSLFSlideShow(hss_one); - hss_two = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss_two = new HSLFSlideShow(hss_two); + hss_two = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss_two = new HSLFSlideShow(hss_two); - hss_three = new HSLFSlideShowImpl(slTests.openResourceAsStream("incorrect_slide_order.ppt")); - ss_three = new HSLFSlideShow(hss_three); - } + hss_three = new HSLFSlideShowImpl(slTests.openResourceAsStream("incorrect_slide_order.ppt")); + ss_three = new HSLFSlideShow(hss_three); + } - /** - * Test that we can "re-order" a slideshow with only 1 slide on it - */ - @Test - void testReOrder1() throws IOException { - // Has one slide - assertEquals(1, ss_one.getSlides().size()); - HSLFSlide s1 = ss_one.getSlides().get(0); + /** + * Test that we can "re-order" a slideshow with only 1 slide on it + */ + @Test + void testReOrder1() throws IOException { + // Has one slide + assertEquals(1, ss_one.getSlides().size()); + HSLFSlide s1 = ss_one.getSlides().get(0); - // Check slide 1 is as expected - assertEquals(256, s1._getSheetNumber()); - assertEquals(3, s1._getSheetRefId()); - assertEquals(1, s1.getSlideNumber()); + // Check slide 1 is as expected + assertEquals(256, s1._getSheetNumber()); + assertEquals(3, s1._getSheetRefId()); + assertEquals(1, s1.getSlideNumber()); - // Now move it to one - ss_one.reorderSlide(1, 1); + // Now move it to one + ss_one.reorderSlide(1, 1); - // Write out, and read back in + // Write out, and read back in HSLFSlideShow ss_read = HSLFTestDataSamples.writeOutAndReadBack(ss_one); - // Check it still has 1 slide - assertEquals(1, ss_read.getSlides().size()); + // Check it still has 1 slide + assertEquals(1, ss_read.getSlides().size()); - // And check it's as expected - s1 = ss_read.getSlides().get(0); - assertEquals(256, s1._getSheetNumber()); - assertEquals(3, s1._getSheetRefId()); - assertEquals(1, s1.getSlideNumber()); + // And check it's as expected + s1 = ss_read.getSlides().get(0); + assertEquals(256, s1._getSheetNumber()); + assertEquals(3, s1._getSheetRefId()); + assertEquals(1, s1.getSlideNumber()); - ss_read.close(); - } + ss_read.close(); + } - /** - * Test doing a dummy re-order on a slideshow with - * two slides in it - */ + /** + * Test doing a dummy re-order on a slideshow with + * two slides in it + */ @Test - void testReOrder2() throws IOException { - // Has two slides - assertEquals(2, ss_two.getSlides().size()); - HSLFSlide s1 = ss_two.getSlides().get(0); - HSLFSlide s2 = ss_two.getSlides().get(1); - - // Check slide 1 is as expected - assertEquals(256, s1._getSheetNumber()); - assertEquals(4, s1._getSheetRefId()); // master has notes - assertEquals(1, s1.getSlideNumber()); - // Check slide 2 is as expected - assertEquals(257, s2._getSheetNumber()); - assertEquals(6, s2._getSheetRefId()); // master and 1 have notes - assertEquals(2, s2.getSlideNumber()); - - // Don't swap them around - ss_two.reorderSlide(2, 2); - - // Write out, and read back in - HSLFSlideShow ss_read = HSLFTestDataSamples.writeOutAndReadBack(ss_two); + void testReOrder2() throws IOException { + // Has two slides + assertEquals(2, ss_two.getSlides().size()); + HSLFSlide s1 = ss_two.getSlides().get(0); + HSLFSlide s2 = ss_two.getSlides().get(1); + + // Check slide 1 is as expected + assertEquals(256, s1._getSheetNumber()); + assertEquals(4, s1._getSheetRefId()); // master has notes + assertEquals(1, s1.getSlideNumber()); + // Check slide 2 is as expected + assertEquals(257, s2._getSheetNumber()); + assertEquals(6, s2._getSheetRefId()); // master and 1 have notes + assertEquals(2, s2.getSlideNumber()); - // Check it still has 2 slides - assertEquals(2, ss_read.getSlides().size()); + // Don't swap them around + ss_two.reorderSlide(2, 2); - // And check it's as expected - s1 = ss_read.getSlides().get(0); - s2 = ss_read.getSlides().get(1); - assertEquals(256, s1._getSheetNumber()); - assertEquals(4, s1._getSheetRefId()); - assertEquals(1, s1.getSlideNumber()); - assertEquals(257, s2._getSheetNumber()); - assertEquals(6, s2._getSheetRefId()); - assertEquals(2, s2.getSlideNumber()); + // Write out, and read back in + HSLFSlideShow ss_read = HSLFTestDataSamples.writeOutAndReadBack(ss_two); + + // Check it still has 2 slides + assertEquals(2, ss_read.getSlides().size()); + + // And check it's as expected + s1 = ss_read.getSlides().get(0); + s2 = ss_read.getSlides().get(1); + assertEquals(256, s1._getSheetNumber()); + assertEquals(4, s1._getSheetRefId()); + assertEquals(1, s1.getSlideNumber()); + assertEquals(257, s2._getSheetNumber()); + assertEquals(6, s2._getSheetRefId()); + assertEquals(2, s2.getSlideNumber()); ss_read.close(); } - /** - * Test re-ordering slides in a slideshow with 2 slides on it - */ + /** + * Test re-ordering slides in a slideshow with 2 slides on it + */ @Test - void testReOrder2swap() throws IOException { - // Has two slides - assertEquals(2, ss_two.getSlides().size()); - HSLFSlide s1 = ss_two.getSlides().get(0); - HSLFSlide s2 = ss_two.getSlides().get(1); - - // Check slide 1 is as expected - assertEquals(256, s1._getSheetNumber()); - assertEquals(4, s1._getSheetRefId()); // master has notes - assertEquals(1, s1.getSlideNumber()); - // Check slide 2 is as expected - assertEquals(257, s2._getSheetNumber()); - assertEquals(6, s2._getSheetRefId()); // master and 1 have notes - assertEquals(2, s2.getSlideNumber()); - - // Swap them around - ss_two.reorderSlide(2, 1); - - // Write out, and read back in - HSLFSlideShow ss_read = HSLFTestDataSamples.writeOutAndReadBack(ss_two); + void testReOrder2swap() throws IOException { + // Has two slides + assertEquals(2, ss_two.getSlides().size()); + HSLFSlide s1 = ss_two.getSlides().get(0); + HSLFSlide s2 = ss_two.getSlides().get(1); + + // Check slide 1 is as expected + assertEquals(256, s1._getSheetNumber()); + assertEquals(4, s1._getSheetRefId()); // master has notes + assertEquals(1, s1.getSlideNumber()); + // Check slide 2 is as expected + assertEquals(257, s2._getSheetNumber()); + assertEquals(6, s2._getSheetRefId()); // master and 1 have notes + assertEquals(2, s2.getSlideNumber()); - // Check it still has 2 slides - assertEquals(2, ss_read.getSlides().size()); + // Swap them around + ss_two.reorderSlide(2, 1); - // And check it's as expected - s1 = ss_read.getSlides().get(0); - s2 = ss_read.getSlides().get(1); - assertEquals(257, s1._getSheetNumber()); - assertEquals(6, s1._getSheetRefId()); - assertEquals(1, s1.getSlideNumber()); - assertEquals(256, s2._getSheetNumber()); - assertEquals(4, s2._getSheetRefId()); - assertEquals(2, s2.getSlideNumber()); + // Write out, and read back in + HSLFSlideShow ss_read = HSLFTestDataSamples.writeOutAndReadBack(ss_two); - ss_read.close(); + // Check it still has 2 slides + assertEquals(2, ss_read.getSlides().size()); + + // And check it's as expected + s1 = ss_read.getSlides().get(0); + s2 = ss_read.getSlides().get(1); + assertEquals(257, s1._getSheetNumber()); + assertEquals(6, s1._getSheetRefId()); + assertEquals(1, s1.getSlideNumber()); + assertEquals(256, s2._getSheetNumber()); + assertEquals(4, s2._getSheetRefId()); + assertEquals(2, s2.getSlideNumber()); + + ss_read.close(); } - /** - * Test doing a dummy re-order on a slideshow with - * three slides in it - */ + /** + * Test doing a dummy re-order on a slideshow with + * three slides in it + */ @Test - void testReOrder3() throws IOException { - // Has three slides - assertEquals(3, ss_three.getSlides().size()); - HSLFSlide s1 = ss_three.getSlides().get(0); - HSLFSlide s2 = ss_three.getSlides().get(1); - HSLFSlide s3 = ss_three.getSlides().get(2); - - // Check slide 1 is as expected - assertEquals(256, s1._getSheetNumber()); - assertEquals(3, s1._getSheetRefId()); // no notes on master - assertEquals(1, s1.getSlideNumber()); - // Check slide 2 is as expected (was re-ordered from 3) - assertEquals(258, s2._getSheetNumber()); - assertEquals(5, s2._getSheetRefId()); // no notes on slide - assertEquals(2, s2.getSlideNumber()); - // Check slide 3 is as expected (was re-ordered from 2) - assertEquals(257, s3._getSheetNumber()); - assertEquals(4, s3._getSheetRefId()); // no notes on slide - assertEquals(3, s3.getSlideNumber()); - - // Don't swap them around - ss_three.reorderSlide(2, 2); - - // Write out, and read back in + void testReOrder3() throws IOException { + // Has three slides + assertEquals(3, ss_three.getSlides().size()); + HSLFSlide s1 = ss_three.getSlides().get(0); + HSLFSlide s2 = ss_three.getSlides().get(1); + HSLFSlide s3 = ss_three.getSlides().get(2); + + // Check slide 1 is as expected + assertEquals(256, s1._getSheetNumber()); + assertEquals(3, s1._getSheetRefId()); // no notes on master + assertEquals(1, s1.getSlideNumber()); + // Check slide 2 is as expected (was re-ordered from 3) + assertEquals(258, s2._getSheetNumber()); + assertEquals(5, s2._getSheetRefId()); // no notes on slide + assertEquals(2, s2.getSlideNumber()); + // Check slide 3 is as expected (was re-ordered from 2) + assertEquals(257, s3._getSheetNumber()); + assertEquals(4, s3._getSheetRefId()); // no notes on slide + assertEquals(3, s3.getSlideNumber()); + + // Don't swap them around + ss_three.reorderSlide(2, 2); + + // Write out, and read back in HSLFSlideShow ss_read = HSLFTestDataSamples.writeOutAndReadBack(ss_three); - // Check it still has 3 slides - assertEquals(3, ss_read.getSlides().size()); + // Check it still has 3 slides + assertEquals(3, ss_read.getSlides().size()); - // And check it's as expected - s1 = ss_read.getSlides().get(0); - s2 = ss_read.getSlides().get(1); - s3 = ss_read.getSlides().get(2); + // And check it's as expected + s1 = ss_read.getSlides().get(0); + s2 = ss_read.getSlides().get(1); + s3 = ss_read.getSlides().get(2); - assertEquals(256, s1._getSheetNumber()); - assertEquals(3, s1._getSheetRefId()); - assertEquals(1, s1.getSlideNumber()); - assertEquals(258, s2._getSheetNumber()); - assertEquals(5, s2._getSheetRefId()); - assertEquals(2, s2.getSlideNumber()); - assertEquals(257, s3._getSheetNumber()); - assertEquals(4, s3._getSheetRefId()); - assertEquals(3, s3.getSlideNumber()); + assertEquals(256, s1._getSheetNumber()); + assertEquals(3, s1._getSheetRefId()); + assertEquals(1, s1.getSlideNumber()); + assertEquals(258, s2._getSheetNumber()); + assertEquals(5, s2._getSheetRefId()); + assertEquals(2, s2.getSlideNumber()); + assertEquals(257, s3._getSheetNumber()); + assertEquals(4, s3._getSheetRefId()); + assertEquals(3, s3.getSlideNumber()); ss_read.close(); } - /** - * Test re-ordering slides in a slideshow with 3 slides on it - */ + /** + * Test re-ordering slides in a slideshow with 3 slides on it + */ @Test - void testReOrder3swap() throws IOException { - // Has three slides - assertEquals(3, ss_three.getSlides().size()); - HSLFSlide s1 = ss_three.getSlides().get(0); - HSLFSlide s2 = ss_three.getSlides().get(1); - HSLFSlide s3 = ss_three.getSlides().get(2); - - // Check slide 1 is as expected - assertEquals(256, s1._getSheetNumber()); - assertEquals(3, s1._getSheetRefId()); // no notes on master - assertEquals(1, s1.getSlideNumber()); - // Check slide 2 is as expected (was re-ordered from 3) - assertEquals(258, s2._getSheetNumber()); - assertEquals(5, s2._getSheetRefId()); // no notes on slide - assertEquals(2, s2.getSlideNumber()); - // Check slide 3 is as expected (was re-ordered from 2) - assertEquals(257, s3._getSheetNumber()); - assertEquals(4, s3._getSheetRefId()); // no notes on slide - assertEquals(3, s3.getSlideNumber()); - - // Put 3 in place of 1 - // (1 -> 2, 2 -> 3) - ss_three.reorderSlide(3, 1); - - // refresh the slides - s1 = ss_three.getSlides().get(0); + void testReOrder3swap() throws IOException { + // Has three slides + assertEquals(3, ss_three.getSlides().size()); + HSLFSlide s1 = ss_three.getSlides().get(0); + HSLFSlide s2 = ss_three.getSlides().get(1); + HSLFSlide s3 = ss_three.getSlides().get(2); + + // Check slide 1 is as expected + assertEquals(256, s1._getSheetNumber()); + assertEquals(3, s1._getSheetRefId()); // no notes on master + assertEquals(1, s1.getSlideNumber()); + // Check slide 2 is as expected (was re-ordered from 3) + assertEquals(258, s2._getSheetNumber()); + assertEquals(5, s2._getSheetRefId()); // no notes on slide + assertEquals(2, s2.getSlideNumber()); + // Check slide 3 is as expected (was re-ordered from 2) + assertEquals(257, s3._getSheetNumber()); + assertEquals(4, s3._getSheetRefId()); // no notes on slide + assertEquals(3, s3.getSlideNumber()); + + // Put 3 in place of 1 + // (1 -> 2, 2 -> 3) + ss_three.reorderSlide(3, 1); + + // refresh the slides + s1 = ss_three.getSlides().get(0); s2 = ss_three.getSlides().get(1); s3 = ss_three.getSlides().get(2); - assertEquals(1, s1.getSlideNumber()); + assertEquals(1, s1.getSlideNumber()); assertEquals(2, s2.getSlideNumber()); assertEquals(3, s3.getSlideNumber()); assertEquals("Slide 3", ((HSLFTextShape)s1.getShapes().get(0)).getText()); assertEquals("Slide 1", ((HSLFTextShape)s3.getShapes().get(0)).getText()); - // Write out, and read back in + // Write out, and read back in HSLFSlideShow ss_read = HSLFTestDataSamples.writeOutAndReadBack(ss_three); - // Check it still has 3 slides - assertEquals(3, ss_read.getSlides().size()); + // Check it still has 3 slides + assertEquals(3, ss_read.getSlides().size()); - // And check it's as expected - HSLFSlide _s1 = ss_read.getSlides().get(0); - HSLFSlide _s2 = ss_read.getSlides().get(1); - HSLFSlide _s3 = ss_read.getSlides().get(2); + // And check it's as expected + HSLFSlide _s1 = ss_read.getSlides().get(0); + HSLFSlide _s2 = ss_read.getSlides().get(1); + HSLFSlide _s3 = ss_read.getSlides().get(2); // 1 --> 3 assertEquals(s1._getSheetNumber(), _s1._getSheetNumber()); - assertEquals(s1._getSheetRefId(), _s1._getSheetRefId()); - assertEquals(1, s1.getSlideNumber()); + assertEquals(s1._getSheetRefId(), _s1._getSheetRefId()); + assertEquals(1, s1.getSlideNumber()); // 2nd slide is not updated assertEquals(s2._getSheetNumber(), _s2._getSheetNumber()); assertEquals(s2._getSheetRefId(), _s2._getSheetRefId()); - assertEquals(2, s2.getSlideNumber()); + assertEquals(2, s2.getSlideNumber()); // 3 --> 1 assertEquals(s3._getSheetNumber(), _s3._getSheetNumber()); assertEquals(s3._getSheetRefId(), _s3._getSheetRefId()); - assertEquals(3, s3.getSlideNumber()); + assertEquals(3, s3.getSlideNumber()); - ss_read.close(); - } + ss_read.close(); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestRecordSetup.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestRecordSetup.java index 962cc7e4d4..126d34c45f 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestRecordSetup.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestRecordSetup.java @@ -30,36 +30,36 @@ import org.junit.jupiter.api.Test; * Note: most recent record stuff has its own test */ public final class TestRecordSetup { - // SlideShow primed on the test data - @SuppressWarnings("unused") + // SlideShow primed on the test data + @SuppressWarnings("unused") private HSLFSlideShow ss; - private HSLFSlideShowImpl hss; + private HSLFSlideShowImpl hss; - @BeforeEach - void init() throws Exception { + @BeforeEach + void init() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new HSLFSlideShow(hss); - } + hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); + } - @Test - void testHandleParentAwareRecords() { - org.apache.poi.hslf.record.Record[] records = hss.getRecords(); - for ( org.apache.poi.hslf.record.Record record : records) { - ensureParentAware(record,null); - } - } - private void ensureParentAware( org.apache.poi.hslf.record.Record r,RecordContainer parent) { - if(r instanceof ParentAwareRecord) { - ParentAwareRecord pr = (ParentAwareRecord)r; - assertEquals(parent, pr.getParentRecord()); - } - if(r instanceof RecordContainer) { - RecordContainer rc = (RecordContainer)r; - org.apache.poi.hslf.record.Record[] children = rc.getChildRecords(); - for ( org.apache.poi.hslf.record.Record rec : children) { - ensureParentAware(rec, rc); - } - } - } + @Test + void testHandleParentAwareRecords() { + org.apache.poi.hslf.record.Record[] records = hss.getRecords(); + for ( org.apache.poi.hslf.record.Record record : records) { + ensureParentAware(record,null); + } + } + private void ensureParentAware( org.apache.poi.hslf.record.Record r,RecordContainer parent) { + if(r instanceof ParentAwareRecord) { + ParentAwareRecord pr = (ParentAwareRecord)r; + assertEquals(parent, pr.getParentRecord()); + } + if(r instanceof RecordContainer) { + RecordContainer rc = (RecordContainer)r; + org.apache.poi.hslf.record.Record[] children = rc.getChildRecords(); + for ( org.apache.poi.hslf.record.Record rec : children) { + ensureParentAware(rec, rc); + } + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestRichTextRun.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestRichTextRun.java index 90a84b815e..87fb7e0033 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestRichTextRun.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestRichTextRun.java @@ -81,554 +81,554 @@ public final class TestRichTextRun { ssChinese.close(); } - /** - * Test the stuff about getting/setting bold - * on a non rich text run - */ + /** + * Test the stuff about getting/setting bold + * on a non rich text run + */ @Test - void testBoldNonRich() { - HSLFSlide slideOne = ss.getSlides().get(0); - List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); - List<HSLFTextParagraph> textParas = textParass.get(0); - HSLFTextRun rtr = textParas.get(0).getTextRuns().get(0); - - assertNotNull(rtr.getCharacterStyle()); - assertNotNull(textParas.get(0).getParagraphStyle()); - assertFalse(rtr.isBold()); - - // Now set it to not bold - rtr.setBold(false); - // in Pre 3.12: setting bold=false doesn't change the internal state - // now: also allow explicitly disable styles and there aren't any non rich text runs anymore - assertNotNull(rtr.getCharacterStyle()); - assertNotNull(textParas.get(0).getParagraphStyle()); - - assertFalse(rtr.isBold()); - - // And now make it bold - rtr.setBold(true); - assertNotNull(rtr.getCharacterStyle()); + void testBoldNonRich() { + HSLFSlide slideOne = ss.getSlides().get(0); + List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); + List<HSLFTextParagraph> textParas = textParass.get(0); + HSLFTextRun rtr = textParas.get(0).getTextRuns().get(0); + + assertNotNull(rtr.getCharacterStyle()); + assertNotNull(textParas.get(0).getParagraphStyle()); + assertFalse(rtr.isBold()); + + // Now set it to not bold + rtr.setBold(false); + // in Pre 3.12: setting bold=false doesn't change the internal state + // now: also allow explicitly disable styles and there aren't any non rich text runs anymore + assertNotNull(rtr.getCharacterStyle()); assertNotNull(textParas.get(0).getParagraphStyle()); - assertTrue(rtr.isBold()); - } - /** - * Test the stuff about getting/setting bold - * on a rich text run - */ + assertFalse(rtr.isBold()); + + // And now make it bold + rtr.setBold(true); + assertNotNull(rtr.getCharacterStyle()); + assertNotNull(textParas.get(0).getParagraphStyle()); + assertTrue(rtr.isBold()); + } + + /** + * Test the stuff about getting/setting bold + * on a rich text run + */ @Test - void testBoldRich() { - HSLFSlide slideOneR = ssRichA.getSlides().get(0); - List<List<HSLFTextParagraph>> textParass = slideOneR.getTextParagraphs(); - List<HSLFTextParagraph> textParas = textParass.get(1); - assertEquals(3, textParas.size()); + void testBoldRich() { + HSLFSlide slideOneR = ssRichA.getSlides().get(0); + List<List<HSLFTextParagraph>> textParass = slideOneR.getTextParagraphs(); + List<HSLFTextParagraph> textParas = textParass.get(1); + assertEquals(3, textParas.size()); - assertTrue(textParas.get(0).getTextRuns().get(0).isBold()); - assertFalse(textParas.get(1).getTextRuns().get(0).isBold()); - assertFalse(textParas.get(2).getTextRuns().get(0).isBold()); + assertTrue(textParas.get(0).getTextRuns().get(0).isBold()); + assertFalse(textParas.get(1).getTextRuns().get(0).isBold()); + assertFalse(textParas.get(2).getTextRuns().get(0).isBold()); - textParas.get(0).getTextRuns().get(0).setBold(true); - textParas.get(1).getTextRuns().get(0).setBold(true); + textParas.get(0).getTextRuns().get(0).setBold(true); + textParas.get(1).getTextRuns().get(0).setBold(true); - assertTrue(textParas.get(0).getTextRuns().get(0).isBold()); - assertTrue(textParas.get(1).getTextRuns().get(0).isBold()); + assertTrue(textParas.get(0).getTextRuns().get(0).isBold()); + assertTrue(textParas.get(1).getTextRuns().get(0).isBold()); - textParas.get(0).getTextRuns().get(0).setBold(false); - textParas.get(1).getTextRuns().get(0).setBold(false); + textParas.get(0).getTextRuns().get(0).setBold(false); + textParas.get(1).getTextRuns().get(0).setBold(false); - assertFalse(textParas.get(0).getTextRuns().get(0).isBold()); - assertFalse(textParas.get(1).getTextRuns().get(0).isBold()); - } + assertFalse(textParas.get(0).getTextRuns().get(0).isBold()); + assertFalse(textParas.get(1).getTextRuns().get(0).isBold()); + } - /** - * Tests getting and setting the font size on rich and non - * rich text runs - */ + /** + * Tests getting and setting the font size on rich and non + * rich text runs + */ @Test - void testFontSize() { - - HSLFSlide slideOne = ss.getSlides().get(0); - List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); - HSLFTextRun rtr = textParass.get(0).get(0).getTextRuns().get(0); - - HSLFSlide slideOneR = ssRichB.getSlides().get(0); - List<List<HSLFTextParagraph>> textParassR = slideOneR.getTextParagraphs(); - HSLFTextRun rtrRa = textParassR.get(0).get(0).getTextRuns().get(0); - HSLFTextRun rtrRb = textParassR.get(1).get(0).getTextRuns().get(0); - HSLFTextRun rtrRc = textParassR.get(1).get(3).getTextRuns().get(0); - - String defaultFont = "Arial"; - - // Start off with rich one - // First run has defaults - assertNotNull(rtrRa.getFontSize()); - assertEquals(44, rtrRa.getFontSize(), 0); - assertEquals(defaultFont, rtrRa.getFontFamily()); - - // Second is size 20, default font - assertNotNull(rtrRb.getFontSize()); - assertEquals(20, rtrRb.getFontSize(), 0); - assertEquals(defaultFont, rtrRb.getFontFamily()); - // Third is size 24, alt font - assertNotNull(rtrRc.getFontSize()); - assertEquals(24, rtrRc.getFontSize(), 0); - assertEquals("Times New Roman", rtrRc.getFontFamily()); - - // Change 2nd to different size and font - assertEquals(2, ssRichB.getFontCollection().getChildRecords().length); // Default + TNR - rtrRb.setFontSize(18d); - rtrRb.setFontFamily("Courier"); - assertEquals(3, ssRichB.getFontCollection().getChildRecords().length); // Default + TNR + Courier - assertEquals(18, rtrRb.getFontSize(), 0); - assertEquals("Courier", rtrRb.getFontFamily()); - - - // Now do non rich one - assertNotNull(rtr.getFontSize()); - assertEquals(44, rtr.getFontSize(), 0); - assertEquals(defaultFont, rtr.getFontFamily()); - assertEquals(1, ss.getFontCollection().getChildRecords().length); // Default - assertNotNull(rtr.getCharacterStyle()); - assertNotNull(rtr.getTextParagraph().getParagraphStyle()); - - // Change Font size - rtr.setFontSize(99d); - assertEquals(99, rtr.getFontSize(), 0); - assertEquals(defaultFont, rtr.getFontFamily()); - assertNotNull(rtr.getCharacterStyle()); - assertNotNull(rtr.getTextParagraph().getParagraphStyle()); - assertEquals(1, ss.getFontCollection().getChildRecords().length); // Default - - // Change Font size and name - rtr.setFontSize(25d); - rtr.setFontFamily("Times New Roman"); - assertEquals(25, rtr.getFontSize(), 0); - assertEquals("Times New Roman", rtr.getFontFamily()); - assertNotNull(rtr.getCharacterStyle()); - assertNotNull(rtr.getTextParagraph().getParagraphStyle()); - assertEquals(2, ss.getFontCollection().getChildRecords().length); - } + void testFontSize() { + + HSLFSlide slideOne = ss.getSlides().get(0); + List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); + HSLFTextRun rtr = textParass.get(0).get(0).getTextRuns().get(0); + + HSLFSlide slideOneR = ssRichB.getSlides().get(0); + List<List<HSLFTextParagraph>> textParassR = slideOneR.getTextParagraphs(); + HSLFTextRun rtrRa = textParassR.get(0).get(0).getTextRuns().get(0); + HSLFTextRun rtrRb = textParassR.get(1).get(0).getTextRuns().get(0); + HSLFTextRun rtrRc = textParassR.get(1).get(3).getTextRuns().get(0); + + String defaultFont = "Arial"; + + // Start off with rich one + // First run has defaults + assertNotNull(rtrRa.getFontSize()); + assertEquals(44, rtrRa.getFontSize(), 0); + assertEquals(defaultFont, rtrRa.getFontFamily()); + + // Second is size 20, default font + assertNotNull(rtrRb.getFontSize()); + assertEquals(20, rtrRb.getFontSize(), 0); + assertEquals(defaultFont, rtrRb.getFontFamily()); + // Third is size 24, alt font + assertNotNull(rtrRc.getFontSize()); + assertEquals(24, rtrRc.getFontSize(), 0); + assertEquals("Times New Roman", rtrRc.getFontFamily()); + + // Change 2nd to different size and font + assertEquals(2, ssRichB.getFontCollection().getChildRecords().length); // Default + TNR + rtrRb.setFontSize(18d); + rtrRb.setFontFamily("Courier"); + assertEquals(3, ssRichB.getFontCollection().getChildRecords().length); // Default + TNR + Courier + assertEquals(18, rtrRb.getFontSize(), 0); + assertEquals("Courier", rtrRb.getFontFamily()); + + + // Now do non rich one + assertNotNull(rtr.getFontSize()); + assertEquals(44, rtr.getFontSize(), 0); + assertEquals(defaultFont, rtr.getFontFamily()); + assertEquals(1, ss.getFontCollection().getChildRecords().length); // Default + assertNotNull(rtr.getCharacterStyle()); + assertNotNull(rtr.getTextParagraph().getParagraphStyle()); + + // Change Font size + rtr.setFontSize(99d); + assertEquals(99, rtr.getFontSize(), 0); + assertEquals(defaultFont, rtr.getFontFamily()); + assertNotNull(rtr.getCharacterStyle()); + assertNotNull(rtr.getTextParagraph().getParagraphStyle()); + assertEquals(1, ss.getFontCollection().getChildRecords().length); // Default + + // Change Font size and name + rtr.setFontSize(25d); + rtr.setFontFamily("Times New Roman"); + assertEquals(25, rtr.getFontSize(), 0); + assertEquals("Times New Roman", rtr.getFontFamily()); + assertNotNull(rtr.getCharacterStyle()); + assertNotNull(rtr.getTextParagraph().getParagraphStyle()); + assertEquals(2, ss.getFontCollection().getChildRecords().length); + } @Test - void testChangeWriteRead() throws IOException { - for(HSLFSlideShow h : new HSLFSlideShow[] { ss, ssRichA, ssRichB }) { - // Change - HSLFSlide slideOne = h.getSlides().get(0); - List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); - HSLFTextRun rtr = textParass.get(0).get(0).getTextRuns().get(0); - - rtr.setBold(true); - rtr.setFontSize(18d); - rtr.setFontFamily("Courier"); + void testChangeWriteRead() throws IOException { + for(HSLFSlideShow h : new HSLFSlideShow[] { ss, ssRichA, ssRichB }) { + // Change + HSLFSlide slideOne = h.getSlides().get(0); + List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); + HSLFTextRun rtr = textParass.get(0).get(0).getTextRuns().get(0); + + rtr.setBold(true); + rtr.setFontSize(18d); + rtr.setFontFamily("Courier"); HSLFTextParagraph.storeText(textParass.get(0)); - // Check it took those - assertTrue(rtr.isBold()); - assertNotNull(rtr.getFontSize()); - assertEquals(18., rtr.getFontSize(), 0); - assertEquals("Courier", rtr.getFontFamily()); - - // Write out and back in - try (HSLFSlideShow readS = HSLFTestDataSamples.writeOutAndReadBack(h)) { - - // Tweak existing one again, to ensure really worked - rtr.setBold(false); - rtr.setFontSize(17d); - rtr.setFontFamily("CourierZZ"); - - // Check it took those changes - assertFalse(rtr.isBold()); - assertEquals(17., rtr.getFontSize(), 0); - assertEquals("CourierZZ", rtr.getFontFamily()); - - - // Now, look at the one we changed, wrote out, and read back in - // Ensure it does contain our original modifications - HSLFSlide slideOneRR = readS.getSlides().get(0); - List<List<HSLFTextParagraph>> textParassRR = slideOneRR.getTextParagraphs(); - HSLFTextRun rtrRRa = textParassRR.get(0).get(0).getTextRuns().get(0); - - assertTrue(rtrRRa.isBold()); - assertNotNull(rtrRRa.getFontSize()); - assertEquals(18., rtrRRa.getFontSize(), 0); - assertEquals("Courier", rtrRRa.getFontFamily()); - } - } - } - - /** - * Test that we can do the right things when the paragraph styles - * run out before the character styles do - */ + // Check it took those + assertTrue(rtr.isBold()); + assertNotNull(rtr.getFontSize()); + assertEquals(18., rtr.getFontSize(), 0); + assertEquals("Courier", rtr.getFontFamily()); + + // Write out and back in + try (HSLFSlideShow readS = HSLFTestDataSamples.writeOutAndReadBack(h)) { + + // Tweak existing one again, to ensure really worked + rtr.setBold(false); + rtr.setFontSize(17d); + rtr.setFontFamily("CourierZZ"); + + // Check it took those changes + assertFalse(rtr.isBold()); + assertEquals(17., rtr.getFontSize(), 0); + assertEquals("CourierZZ", rtr.getFontFamily()); + + + // Now, look at the one we changed, wrote out, and read back in + // Ensure it does contain our original modifications + HSLFSlide slideOneRR = readS.getSlides().get(0); + List<List<HSLFTextParagraph>> textParassRR = slideOneRR.getTextParagraphs(); + HSLFTextRun rtrRRa = textParassRR.get(0).get(0).getTextRuns().get(0); + + assertTrue(rtrRRa.isBold()); + assertNotNull(rtrRRa.getFontSize()); + assertEquals(18., rtrRRa.getFontSize(), 0); + assertEquals("Courier", rtrRRa.getFontFamily()); + } + } + } + + /** + * Test that we can do the right things when the paragraph styles + * run out before the character styles do + */ @Test - void testParagraphStylesShorterTheCharStyles() { - // Check we have the right number of sheets - List<HSLFSlide> slides = ssRichC.getSlides(); - assertEquals(14, slides.size()); - - // Check the number of text runs on interesting sheets - HSLFSlide slideThreeC = ssRichC.getSlides().get(2); - HSLFSlide slideSevenC = ssRichC.getSlides().get(6); - assertEquals(4, slideThreeC.getTextParagraphs().size()); - assertEquals(5, slideSevenC.getTextParagraphs().size()); - - // On slide three, we should have: - // TR: - // You are an important supplier of various items that I need - // . - // TR: - // Source: Internal focus groups - // TR: - // Illustrative Example - // . + void testParagraphStylesShorterTheCharStyles() { + // Check we have the right number of sheets + List<HSLFSlide> slides = ssRichC.getSlides(); + assertEquals(14, slides.size()); + + // Check the number of text runs on interesting sheets + HSLFSlide slideThreeC = ssRichC.getSlides().get(2); + HSLFSlide slideSevenC = ssRichC.getSlides().get(6); + assertEquals(4, slideThreeC.getTextParagraphs().size()); + assertEquals(5, slideSevenC.getTextParagraphs().size()); + + // On slide three, we should have: + // TR: + // You are an important supplier of various items that I need + // . + // TR: + // Source: Internal focus groups + // TR: + // Illustrative Example + // . List<List<HSLFTextParagraph>> s3tr = slideThreeC.getTextParagraphs(); - List<HSLFTextRun> s3rtr0 = s3tr.get(0).get(0).getTextRuns(); - List<HSLFTextRun> s3rtr1 = s3tr.get(2).get(0).getTextRuns(); - List<HSLFTextRun> s3rtr2 = s3tr.get(3).get(0).getTextRuns(); - - assertEquals(2, s3rtr0.size()); - assertEquals(1, s3rtr1.size()); - assertEquals(2, s3rtr2.size()); - - assertEquals("You are an important supplier of various items that I need", s3rtr0.get(0).getRawText()); - assertEquals("", s3rtr0.get(1).getRawText()); - assertEquals("Source: Internal focus groups", s3rtr1.get(0).getRawText()); - assertEquals("Illustrative Example", s3rtr2.get(0).getRawText()); - assertEquals("", s3rtr2.get(1).getRawText()); - - // On slide seven, we have: - // TR: - // (text) - // TR: - // <ps>(text a)</ps><ps>(text a)(text b)</ps> - // TR: - // (text) - List<List<HSLFTextParagraph>> s7tr = slideSevenC.getTextParagraphs(); - List<HSLFTextParagraph> s7rtr0 = s7tr.get(0); - List<HSLFTextParagraph> s7rtr1 = s7tr.get(1); - List<HSLFTextParagraph> s7rtr2 = s7tr.get(2); - - assertEquals(1, s7rtr0.size()); - assertEquals(8, s7rtr1.size()); - assertEquals(1, s7rtr2.size()); - } - - /** - * Test that we can do the right things when the paragraph styles - * run out before the character styles do, when we tweak something - * and write back out. - */ + List<HSLFTextRun> s3rtr0 = s3tr.get(0).get(0).getTextRuns(); + List<HSLFTextRun> s3rtr1 = s3tr.get(2).get(0).getTextRuns(); + List<HSLFTextRun> s3rtr2 = s3tr.get(3).get(0).getTextRuns(); + + assertEquals(2, s3rtr0.size()); + assertEquals(1, s3rtr1.size()); + assertEquals(2, s3rtr2.size()); + + assertEquals("You are an important supplier of various items that I need", s3rtr0.get(0).getRawText()); + assertEquals("", s3rtr0.get(1).getRawText()); + assertEquals("Source: Internal focus groups", s3rtr1.get(0).getRawText()); + assertEquals("Illustrative Example", s3rtr2.get(0).getRawText()); + assertEquals("", s3rtr2.get(1).getRawText()); + + // On slide seven, we have: + // TR: + // (text) + // TR: + // <ps>(text a)</ps><ps>(text a)(text b)</ps> + // TR: + // (text) + List<List<HSLFTextParagraph>> s7tr = slideSevenC.getTextParagraphs(); + List<HSLFTextParagraph> s7rtr0 = s7tr.get(0); + List<HSLFTextParagraph> s7rtr1 = s7tr.get(1); + List<HSLFTextParagraph> s7rtr2 = s7tr.get(2); + + assertEquals(1, s7rtr0.size()); + assertEquals(8, s7rtr1.size()); + assertEquals(1, s7rtr2.size()); + } + + /** + * Test that we can do the right things when the paragraph styles + * run out before the character styles do, when we tweak something + * and write back out. + */ @Test - @SuppressWarnings("unused") + @SuppressWarnings("unused") void testParagraphStylesShorterTheCharStylesWrite() throws IOException { - assertMatchesSLTWC(ssRichC); - assertMatchesFileC(ssRichC); - - HSLFSlide slideSevenC = ssRichC.getSlides().get(6); - List<List<HSLFTextParagraph>> s7tr = slideSevenC.getTextParagraphs(); - List<HSLFTextRun> s7rtr0 = s7tr.get(0).get(0).getTextRuns(); - List<HSLFTextRun> s7rtr1 = s7tr.get(1).get(0).getTextRuns(); - List<HSLFTextRun> s7rtr2 = s7tr.get(2).get(0).getTextRuns(); - - String oldText; - - // Reset the text on the last run - // Need to ensure it's a run that really has styles! - oldText = s7rtr2.get(0).getRawText(); - s7rtr2.get(0).setText( oldText ); - HSLFTextParagraph.storeText(s7tr.get(2)); - assertEquals(oldText, s7rtr2.get(0).getRawText()); - assertEquals(oldText, HSLFTextParagraph.getRawText(s7tr.get(2))); - assertEquals(oldText.length() + 1, s7rtr2.get(0).getCharacterStyle().getCharactersCovered()); - assertEquals(oldText.length() + 1, s7rtr2.get(0).getTextParagraph().getParagraphStyle().getCharactersCovered()); - assertMatchesSLTWC(ssRichC); - assertMatchesFileC(ssRichC); - - // Reset the text on a shared paragraph - oldText = s7rtr1.get(0).getRawText(); - s7rtr1.get(0).setText( oldText ); + assertMatchesSLTWC(ssRichC); + assertMatchesFileC(ssRichC); + + HSLFSlide slideSevenC = ssRichC.getSlides().get(6); + List<List<HSLFTextParagraph>> s7tr = slideSevenC.getTextParagraphs(); + List<HSLFTextRun> s7rtr0 = s7tr.get(0).get(0).getTextRuns(); + List<HSLFTextRun> s7rtr1 = s7tr.get(1).get(0).getTextRuns(); + List<HSLFTextRun> s7rtr2 = s7tr.get(2).get(0).getTextRuns(); + + String oldText; + + // Reset the text on the last run + // Need to ensure it's a run that really has styles! + oldText = s7rtr2.get(0).getRawText(); + s7rtr2.get(0).setText( oldText ); + HSLFTextParagraph.storeText(s7tr.get(2)); + assertEquals(oldText, s7rtr2.get(0).getRawText()); + assertEquals(oldText, HSLFTextParagraph.getRawText(s7tr.get(2))); + assertEquals(oldText.length() + 1, s7rtr2.get(0).getCharacterStyle().getCharactersCovered()); + assertEquals(oldText.length() + 1, s7rtr2.get(0).getTextParagraph().getParagraphStyle().getCharactersCovered()); + assertMatchesSLTWC(ssRichC); + assertMatchesFileC(ssRichC); + + // Reset the text on a shared paragraph + oldText = s7rtr1.get(0).getRawText(); + s7rtr1.get(0).setText( oldText ); HSLFTextParagraph.storeText(s7tr.get(1)); - assertEquals(oldText, s7rtr1.get(0).getRawText()); - assertEquals(oldText.length(), s7rtr1.get(0).getCharacterStyle().getCharactersCovered()); - assertMatchesSLTWC(ssRichC); - assertMatchesFileC(ssRichC); - - // Reset the text on a shared paragraph+character - s7rtr1.get(0).setText( s7rtr1.get(0).getRawText() ); - HSLFTextParagraph.storeText(s7tr.get(1)); - assertMatchesSLTWC(ssRichC); - assertMatchesFileC(ssRichC); - } - - /** - * Opens a new copy of SlideShow C, writes the active - * SlideListWithText out, and compares it to the write - * out of the supplied SlideShow. Also compares the - * contents. - */ - private void assertMatchesSLTWC(HSLFSlideShow s) throws IOException { - // Grab a new copy of slideshow C - try (HSLFSlideShow refC = HSLFTestDataSamples.getSlideShow(filenameC)) { - - // Write out the 2nd SLWT in the active document - SlideListWithText refSLWT = refC.getDocumentRecord().getSlideListWithTexts()[1]; - byte[] raw_slwt = writeRecord(refSLWT); - - // Write out the same for the supplied slideshow - SlideListWithText s_SLWT = s.getDocumentRecord().getSlideListWithTexts()[1]; - byte[] s_slwt = writeRecord(s_SLWT); - - // Check the records are the same - assertEquals(refSLWT.getChildRecords().length, s_SLWT.getChildRecords().length); - for (int i = 0; i < refSLWT.getChildRecords().length; i++) { - Record ref_r = refSLWT.getChildRecords()[i]; - Record s_r = s_SLWT.getChildRecords()[i]; - - byte[] r_rb = writeRecord(ref_r); - byte[] s_rb = writeRecord(s_r); - assertArrayEquals(r_rb, s_rb); - } - - // Check the bytes are the same - assertArrayEquals(raw_slwt, s_slwt); - } - } - - /** - * Checks that the supplied slideshow still matches the bytes - * of slideshow c - */ - private static void assertMatchesFileC(HSLFSlideShow s) throws IOException { - // Grab the bytes of the file - byte[] raw_file; - try (POIFSFileSystem fs = new POIFSFileSystem(HSLFTestDataSamples.openSampleFileStream(filenameC)); - InputStream is = fs.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT)) { - raw_file = IOUtils.toByteArray(is); - } - - // Now write out the slideshow - byte[] raw_ss; + assertEquals(oldText, s7rtr1.get(0).getRawText()); + assertEquals(oldText.length(), s7rtr1.get(0).getCharacterStyle().getCharactersCovered()); + assertMatchesSLTWC(ssRichC); + assertMatchesFileC(ssRichC); + + // Reset the text on a shared paragraph+character + s7rtr1.get(0).setText( s7rtr1.get(0).getRawText() ); + HSLFTextParagraph.storeText(s7tr.get(1)); + assertMatchesSLTWC(ssRichC); + assertMatchesFileC(ssRichC); + } + + /** + * Opens a new copy of SlideShow C, writes the active + * SlideListWithText out, and compares it to the write + * out of the supplied SlideShow. Also compares the + * contents. + */ + private void assertMatchesSLTWC(HSLFSlideShow s) throws IOException { + // Grab a new copy of slideshow C + try (HSLFSlideShow refC = HSLFTestDataSamples.getSlideShow(filenameC)) { + + // Write out the 2nd SLWT in the active document + SlideListWithText refSLWT = refC.getDocumentRecord().getSlideListWithTexts()[1]; + byte[] raw_slwt = writeRecord(refSLWT); + + // Write out the same for the supplied slideshow + SlideListWithText s_SLWT = s.getDocumentRecord().getSlideListWithTexts()[1]; + byte[] s_slwt = writeRecord(s_SLWT); + + // Check the records are the same + assertEquals(refSLWT.getChildRecords().length, s_SLWT.getChildRecords().length); + for (int i = 0; i < refSLWT.getChildRecords().length; i++) { + Record ref_r = refSLWT.getChildRecords()[i]; + Record s_r = s_SLWT.getChildRecords()[i]; + + byte[] r_rb = writeRecord(ref_r); + byte[] s_rb = writeRecord(s_r); + assertArrayEquals(r_rb, s_rb); + } + + // Check the bytes are the same + assertArrayEquals(raw_slwt, s_slwt); + } + } + + /** + * Checks that the supplied slideshow still matches the bytes + * of slideshow c + */ + private static void assertMatchesFileC(HSLFSlideShow s) throws IOException { + // Grab the bytes of the file + byte[] raw_file; + try (POIFSFileSystem fs = new POIFSFileSystem(HSLFTestDataSamples.openSampleFileStream(filenameC)); + InputStream is = fs.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT)) { + raw_file = IOUtils.toByteArray(is); + } + + // Now write out the slideshow + byte[] raw_ss; UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - s.write(baos); - try (POIFSFileSystem fs = new POIFSFileSystem(baos.toInputStream()); - InputStream is = fs.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT)) { - raw_ss = IOUtils.toByteArray(is); - } + s.write(baos); + try (POIFSFileSystem fs = new POIFSFileSystem(baos.toInputStream()); + InputStream is = fs.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT)) { + raw_ss = IOUtils.toByteArray(is); + } - // different paragraph mask, because of sanitizing - raw_ss[169030] = 0x0a; + // different paragraph mask, because of sanitizing + raw_ss[169030] = 0x0a; - // Ensure they're the same - assertArrayEquals(raw_file, raw_ss); - } + // Ensure they're the same + assertArrayEquals(raw_file, raw_ss); + } - private byte[] writeRecord( org.apache.poi.hslf.record.Record r) throws IOException { - UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); - r.writeOut(baos); - return baos.toByteArray(); - } + private byte[] writeRecord( org.apache.poi.hslf.record.Record r) throws IOException { + UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); + r.writeOut(baos); + return baos.toByteArray(); + } @Test - void testIndentationLevel() throws Exception { - try (HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("ParagraphStylesShorterThanCharStyles.ppt")) { - for (HSLFSlide sl : ppt.getSlides()) { - for (List<HSLFTextParagraph> txt : sl.getTextParagraphs()) { - for (HSLFTextParagraph p : txt) { - int indent = p.getIndentLevel(); - assertTrue(indent >= 0 && indent <= 4); - } - - } - } - } - } + void testIndentationLevel() throws Exception { + try (HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("ParagraphStylesShorterThanCharStyles.ppt")) { + for (HSLFSlide sl : ppt.getSlides()) { + for (List<HSLFTextParagraph> txt : sl.getTextParagraphs()) { + for (HSLFTextParagraph p : txt) { + int indent = p.getIndentLevel(); + assertTrue(indent >= 0 && indent <= 4); + } + + } + } + } + } @Test - void testReadParagraphStyles() throws Exception { - try (HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("bullets.ppt")) { - HSLFTextParagraph rt; - List<List<HSLFTextParagraph>> txt; - List<HSLFSlide> slide = ppt.getSlides(); - assertEquals(2, slide.size()); - - txt = slide.get(0).getTextParagraphs(); - assertEquals(2, txt.size()); - - assertEquals("Title text", HSLFTextParagraph.getRawText(txt.get(0))); - assertEquals(1, txt.get(0).size()); - rt = txt.get(0).get(0); - assertFalse(rt.isBullet()); - - String expected = - "This is a text placeholder that \r" + - "follows the design pattern\r" + - "Defined in the slide master\r" + - "and has bullets by default"; - assertEquals(expected, HSLFTextParagraph.getRawText(txt.get(1))); - assertEquals(4, txt.get(1).size()); - rt = txt.get(1).get(0); - assertNotNull(rt.getBulletChar()); - assertEquals('\u2022', (char) rt.getBulletChar()); - assertTrue(rt.isBullet()); - - - txt = slide.get(1).getTextParagraphs(); - assertEquals(2, txt.size()); - - expected = - "I\u2019m a text box\r" + - "With bullets\r" + - "That follow the design pattern\r" + - "From the slide master"; - assertEquals(expected, HSLFTextParagraph.getRawText(txt.get(0))); - assertEquals(4, txt.get(0).size()); - rt = txt.get(0).get(0); - assertTrue(rt.isBullet()); - assertNotNull(rt.getBulletChar()); - assertEquals('\u2022', (char) rt.getBulletChar()); - - expected = - "I\u2019m a text box with user-defined\r" + - "bullet character"; - assertEquals(expected, HSLFTextParagraph.getRawText(txt.get(1))); - assertEquals(2, txt.get(1).size()); - rt = txt.get(1).get(0); - assertTrue(rt.isBullet()); - assertNotNull(rt.getBulletChar()); - assertEquals('\u263A', (char) rt.getBulletChar()); - } - } + void testReadParagraphStyles() throws Exception { + try (HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("bullets.ppt")) { + HSLFTextParagraph rt; + List<List<HSLFTextParagraph>> txt; + List<HSLFSlide> slide = ppt.getSlides(); + assertEquals(2, slide.size()); + + txt = slide.get(0).getTextParagraphs(); + assertEquals(2, txt.size()); + + assertEquals("Title text", HSLFTextParagraph.getRawText(txt.get(0))); + assertEquals(1, txt.get(0).size()); + rt = txt.get(0).get(0); + assertFalse(rt.isBullet()); + + String expected = + "This is a text placeholder that \r" + + "follows the design pattern\r" + + "Defined in the slide master\r" + + "and has bullets by default"; + assertEquals(expected, HSLFTextParagraph.getRawText(txt.get(1))); + assertEquals(4, txt.get(1).size()); + rt = txt.get(1).get(0); + assertNotNull(rt.getBulletChar()); + assertEquals('\u2022', (char) rt.getBulletChar()); + assertTrue(rt.isBullet()); + + + txt = slide.get(1).getTextParagraphs(); + assertEquals(2, txt.size()); + + expected = + "I\u2019m a text box\r" + + "With bullets\r" + + "That follow the design pattern\r" + + "From the slide master"; + assertEquals(expected, HSLFTextParagraph.getRawText(txt.get(0))); + assertEquals(4, txt.get(0).size()); + rt = txt.get(0).get(0); + assertTrue(rt.isBullet()); + assertNotNull(rt.getBulletChar()); + assertEquals('\u2022', (char) rt.getBulletChar()); + + expected = + "I\u2019m a text box with user-defined\r" + + "bullet character"; + assertEquals(expected, HSLFTextParagraph.getRawText(txt.get(1))); + assertEquals(2, txt.get(1).size()); + rt = txt.get(1).get(0); + assertTrue(rt.isBullet()); + assertNotNull(rt.getBulletChar()); + assertEquals('\u263A', (char) rt.getBulletChar()); + } + } @Test - void testSetParagraphStyles() throws IOException { - try (HSLFSlideShow ppt1 = new HSLFSlideShow()) { - - HSLFSlide slide = ppt1.createSlide(); - - HSLFTextBox shape = new HSLFTextBox(); - shape.setText( - "Hello, World!\r" + - "This should be\r" + - "Multiline text"); - HSLFTextParagraph rt = shape.getTextParagraphs().get(0); - HSLFTextRun tr = rt.getTextRuns().get(0); - tr.setFontSize(42d); - rt.setBullet(true); - rt.setLeftMargin(50d); - rt.setIndent(0d); - rt.setBulletChar('\u263A'); - slide.addShape(shape); - - assertNotNull(tr.getFontSize()); - assertEquals(42.0, tr.getFontSize(), 0); - assertTrue(rt.isBullet()); - assertNotNull(rt.getLeftMargin()); - assertEquals(50.0, rt.getLeftMargin(), 0); - assertNotNull(rt.getIndent()); - assertEquals(0, rt.getIndent(), 0); - assertNotNull(rt.getBulletChar()); - assertEquals('\u263A', (char) rt.getBulletChar()); - - shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300)); - slide.addShape(shape); - - //serialize and read again - try (HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1)) { - slide = ppt2.getSlides().get(0); - shape = (HSLFTextBox) slide.getShapes().get(0); - rt = shape.getTextParagraphs().get(0); - tr = rt.getTextRuns().get(0); - assertNotNull(tr.getFontSize()); - assertEquals(42.0, tr.getFontSize(), 0); - assertTrue(rt.isBullet()); - assertNotNull(rt.getLeftMargin()); - assertEquals(50.0, rt.getLeftMargin(), 0); - assertNotNull(rt.getIndent()); - assertEquals(0, rt.getIndent(), 0); - assertNotNull(rt.getBulletChar()); - assertEquals('\u263A', (char) rt.getBulletChar()); - } - } - } + void testSetParagraphStyles() throws IOException { + try (HSLFSlideShow ppt1 = new HSLFSlideShow()) { + + HSLFSlide slide = ppt1.createSlide(); + + HSLFTextBox shape = new HSLFTextBox(); + shape.setText( + "Hello, World!\r" + + "This should be\r" + + "Multiline text"); + HSLFTextParagraph rt = shape.getTextParagraphs().get(0); + HSLFTextRun tr = rt.getTextRuns().get(0); + tr.setFontSize(42d); + rt.setBullet(true); + rt.setLeftMargin(50d); + rt.setIndent(0d); + rt.setBulletChar('\u263A'); + slide.addShape(shape); + + assertNotNull(tr.getFontSize()); + assertEquals(42.0, tr.getFontSize(), 0); + assertTrue(rt.isBullet()); + assertNotNull(rt.getLeftMargin()); + assertEquals(50.0, rt.getLeftMargin(), 0); + assertNotNull(rt.getIndent()); + assertEquals(0, rt.getIndent(), 0); + assertNotNull(rt.getBulletChar()); + assertEquals('\u263A', (char) rt.getBulletChar()); + + shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300)); + slide.addShape(shape); + + //serialize and read again + try (HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1)) { + slide = ppt2.getSlides().get(0); + shape = (HSLFTextBox) slide.getShapes().get(0); + rt = shape.getTextParagraphs().get(0); + tr = rt.getTextRuns().get(0); + assertNotNull(tr.getFontSize()); + assertEquals(42.0, tr.getFontSize(), 0); + assertTrue(rt.isBullet()); + assertNotNull(rt.getLeftMargin()); + assertEquals(50.0, rt.getLeftMargin(), 0); + assertNotNull(rt.getIndent()); + assertEquals(0, rt.getIndent(), 0); + assertNotNull(rt.getBulletChar()); + assertEquals('\u263A', (char) rt.getBulletChar()); + } + } + } @Test - void testAddText() throws Exception { - try (HSLFSlideShow ppt1 = HSLFTestDataSamples.getSlideShow("bullets.ppt")) { - - HSLFTextParagraph rt; - HSLFTextRun tr; - List<List<HSLFTextParagraph>> txt; - List<HSLFSlide> slides = ppt1.getSlides(); - - assertEquals(2, slides.size()); - txt = slides.get(0).getTextParagraphs(); - assertEquals(2, txt.size()); - - assertEquals("Title text", HSLFTextParagraph.getRawText(txt.get(0))); - assertEquals(1, txt.get(0).size()); - rt = txt.get(0).get(0); - assertFalse(rt.isBullet()); - - // Add some new text - HSLFTextParagraph.appendText(txt.get(0), "Foo! I'm new!", true); - assertEquals(2, txt.get(0).size()); - - rt = txt.get(0).get(0); - tr = rt.getTextRuns().get(0); - assertFalse(tr.isBold()); - assertEquals("Title text\r", tr.getRawText()); - rt = txt.get(0).get(1); - tr = rt.getTextRuns().get(0); - assertFalse(tr.isBold()); - assertEquals("Foo! I'm new!", tr.getRawText()); - tr.setBold(true); - HSLFTextParagraph.storeText(txt.get(0)); - - // And some more, attributes will be copied from previous run - HSLFTextParagraph.appendText(txt.get(0), "Me too!", true); - HSLFTextParagraph.storeText(txt.get(0)); - assertEquals(3, txt.get(0).size()); - rt = txt.get(0).get(0); - tr = rt.getTextRuns().get(0); - assertFalse(tr.isBold()); - assertEquals("Title text\r", tr.getRawText()); - rt = txt.get(0).get(1); - tr = rt.getTextRuns().get(0); - assertTrue(tr.isBold()); - assertEquals("Foo! I'm new!\r", tr.getRawText()); - rt = txt.get(0).get(2); - tr = rt.getTextRuns().get(0); - assertTrue(tr.isBold()); - assertEquals("Me too!", tr.getRawText()); - - // Save and re-open - try (HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1)) { - slides = ppt2.getSlides(); - - assertEquals(2, slides.size()); - - txt = slides.get(0).getTextParagraphs(); - assertEquals(2, txt.size()); - assertEquals(3, txt.get(0).size()); - rt = txt.get(0).get(0); - tr = rt.getTextRuns().get(0); - assertFalse(tr.isBold()); - assertEquals("Title text\r", tr.getRawText()); - rt = txt.get(0).get(1); - tr = rt.getTextRuns().get(0); - assertTrue(tr.isBold()); - assertEquals("Foo! I'm new!\r", tr.getRawText()); - rt = txt.get(0).get(2); - tr = rt.getTextRuns().get(0); - assertTrue(tr.isBold()); - assertEquals("Me too!", tr.getRawText()); - } - } - } + void testAddText() throws Exception { + try (HSLFSlideShow ppt1 = HSLFTestDataSamples.getSlideShow("bullets.ppt")) { + + HSLFTextParagraph rt; + HSLFTextRun tr; + List<List<HSLFTextParagraph>> txt; + List<HSLFSlide> slides = ppt1.getSlides(); + + assertEquals(2, slides.size()); + txt = slides.get(0).getTextParagraphs(); + assertEquals(2, txt.size()); + + assertEquals("Title text", HSLFTextParagraph.getRawText(txt.get(0))); + assertEquals(1, txt.get(0).size()); + rt = txt.get(0).get(0); + assertFalse(rt.isBullet()); + + // Add some new text + HSLFTextParagraph.appendText(txt.get(0), "Foo! I'm new!", true); + assertEquals(2, txt.get(0).size()); + + rt = txt.get(0).get(0); + tr = rt.getTextRuns().get(0); + assertFalse(tr.isBold()); + assertEquals("Title text\r", tr.getRawText()); + rt = txt.get(0).get(1); + tr = rt.getTextRuns().get(0); + assertFalse(tr.isBold()); + assertEquals("Foo! I'm new!", tr.getRawText()); + tr.setBold(true); + HSLFTextParagraph.storeText(txt.get(0)); + + // And some more, attributes will be copied from previous run + HSLFTextParagraph.appendText(txt.get(0), "Me too!", true); + HSLFTextParagraph.storeText(txt.get(0)); + assertEquals(3, txt.get(0).size()); + rt = txt.get(0).get(0); + tr = rt.getTextRuns().get(0); + assertFalse(tr.isBold()); + assertEquals("Title text\r", tr.getRawText()); + rt = txt.get(0).get(1); + tr = rt.getTextRuns().get(0); + assertTrue(tr.isBold()); + assertEquals("Foo! I'm new!\r", tr.getRawText()); + rt = txt.get(0).get(2); + tr = rt.getTextRuns().get(0); + assertTrue(tr.isBold()); + assertEquals("Me too!", tr.getRawText()); + + // Save and re-open + try (HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1)) { + slides = ppt2.getSlides(); + + assertEquals(2, slides.size()); + + txt = slides.get(0).getTextParagraphs(); + assertEquals(2, txt.size()); + assertEquals(3, txt.get(0).size()); + rt = txt.get(0).get(0); + tr = rt.getTextRuns().get(0); + assertFalse(tr.isBold()); + assertEquals("Title text\r", tr.getRawText()); + rt = txt.get(0).get(1); + tr = rt.getTextRuns().get(0); + assertTrue(tr.isBold()); + assertEquals("Foo! I'm new!\r", tr.getRawText()); + rt = txt.get(0).get(2); + tr = rt.getTextRuns().get(0); + assertTrue(tr.isBold()); + assertEquals("Me too!", tr.getRawText()); + } + } + } @Test - void testChineseParagraphs() { + void testChineseParagraphs() { List<HSLFTextRun> rts; HSLFTextRun rt; List<List<HSLFTextParagraph>> txt; @@ -659,5 +659,5 @@ public final class TestRichTextRun { // Font is Calibri assertEquals("Calibri", rt.getFontFamily()); - } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestSheetText.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestSheetText.java index a2c0469bc1..b6f93ec228 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestSheetText.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestSheetText.java @@ -31,66 +31,66 @@ import org.junit.jupiter.api.Test; * Tests that SlideShow returns Sheets which have the right text in them */ public final class TestSheetText { - // SlideShow primed on the test data - private HSLFSlideShow ss; - - @BeforeEach - void init() throws IOException { - ss = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); - } - - @AfterEach - void tearDown() throws IOException { - ss.close(); - } - - @Test - void testSheetOne() { - HSLFSheet slideOne = ss.getSlides().get(0); - - String[] expectText = new String[] {"This is a test title","This is a test subtitle\rThis is on page 1"}; - assertEquals(expectText.length, slideOne.getTextParagraphs().size()); - int i = 0; - for(List<HSLFTextParagraph> textParas : slideOne.getTextParagraphs()) { - assertEquals(expectText[i++], HSLFTextParagraph.getRawText(textParas)); - } - } - - void testSheetTwo() { - HSLFSheet slideTwo = ss.getSlides().get(1); - String[] expectText = new String[] {"This is the title on page 2","This is page two\rIt has several blocks of text\rNone of them have formatting"}; - assertEquals(expectText.length, slideTwo.getTextParagraphs().size()); + // SlideShow primed on the test data + private HSLFSlideShow ss; + + @BeforeEach + void init() throws IOException { + ss = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); + } + + @AfterEach + void tearDown() throws IOException { + ss.close(); + } + + @Test + void testSheetOne() { + HSLFSheet slideOne = ss.getSlides().get(0); + + String[] expectText = new String[] {"This is a test title","This is a test subtitle\rThis is on page 1"}; + assertEquals(expectText.length, slideOne.getTextParagraphs().size()); + int i = 0; + for(List<HSLFTextParagraph> textParas : slideOne.getTextParagraphs()) { + assertEquals(expectText[i++], HSLFTextParagraph.getRawText(textParas)); + } + } + + void testSheetTwo() { + HSLFSheet slideTwo = ss.getSlides().get(1); + String[] expectText = new String[] {"This is the title on page 2","This is page two\rIt has several blocks of text\rNone of them have formatting"}; + assertEquals(expectText.length, slideTwo.getTextParagraphs().size()); int i = 0; for(List<HSLFTextParagraph> textParas : slideTwo.getTextParagraphs()) { assertEquals(expectText[i++], HSLFTextParagraph.getRawText(textParas)); } - } - - /** - * Check we can still get the text from a file where the - * TextProps don't have enough data. - * (Make sure we don't screw up / throw an exception etc) - */ - void testWithShortTextPropData() throws IOException { - HSLFSlideShow sss = HSLFTestDataSamples.getSlideShow("iisd_report.ppt"); - - // Should come out with 10 slides, no notes - assertEquals(10, sss.getSlides().size()); - assertEquals(0, sss.getNotes().size()); - - // Check text on first slide - HSLFSlide s = sss.getSlides().get(0); - String exp = - "Realizing the Development Dividend:\n" + - "Community Capacity Building and CDM.\n" + - "Can they co-exist?\n\n" + - "Gay Harley\n" + - "Clean Development Alliance\n" + - "COP 11 \u2013 MOP 1\n" + // special long hyphen - "December 5, 2005\n"; - - assertEquals(1, s.getTextParagraphs().size()); - assertEquals(exp, HSLFTextParagraph.getRawText(s.getTextParagraphs().get(0))); - sss.close(); - } + } + + /** + * Check we can still get the text from a file where the + * TextProps don't have enough data. + * (Make sure we don't screw up / throw an exception etc) + */ + void testWithShortTextPropData() throws IOException { + HSLFSlideShow sss = HSLFTestDataSamples.getSlideShow("iisd_report.ppt"); + + // Should come out with 10 slides, no notes + assertEquals(10, sss.getSlides().size()); + assertEquals(0, sss.getNotes().size()); + + // Check text on first slide + HSLFSlide s = sss.getSlides().get(0); + String exp = + "Realizing the Development Dividend:\n" + + "Community Capacity Building and CDM.\n" + + "Can they co-exist?\n\n" + + "Gay Harley\n" + + "Clean Development Alliance\n" + + "COP 11 \u2013 MOP 1\n" + // special long hyphen + "December 5, 2005\n"; + + assertEquals(1, s.getTextParagraphs().size()); + assertEquals(exp, HSLFTextParagraph.getRawText(s.getTextParagraphs().get(0))); + sss.close(); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestSlideOrdering.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestSlideOrdering.java index 0a5df4dde3..c4b2853642 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestSlideOrdering.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestSlideOrdering.java @@ -31,104 +31,104 @@ import org.junit.jupiter.api.Test; * Tests that SlideShow returns Sheets in the right order */ public final class TestSlideOrdering { - // Simple slideshow, record order matches slide order - private HSLFSlideShow ssA; - // Complex slideshow, record order doesn't match slide order - private HSLFSlideShow ssB; - - @BeforeEach - void init() throws IOException { - ssA = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); - ssB = HSLFTestDataSamples.getSlideShow("incorrect_slide_order.ppt"); - } - - @AfterEach - void tearDown() throws IOException { - ssA.close(); - ssB.close(); - } - - /** - * Test the simple case - record order matches slide order - */ - @Test - void testSimpleCase() { - assertEquals(2, ssA.getSlides().size()); - - HSLFSlide s1 = ssA.getSlides().get(0); - HSLFSlide s2 = ssA.getSlides().get(1); - - String[] firstTRs = new String[] { "This is a test title", "This is the title on page 2" }; - - assertEquals(firstTRs[0], HSLFTextParagraph.getRawText(s1.getTextParagraphs().get(0))); - assertEquals(firstTRs[1], HSLFTextParagraph.getRawText(s2.getTextParagraphs().get(0))); - } - - /** - * Test the complex case - record order differs from slide order - */ + // Simple slideshow, record order matches slide order + private HSLFSlideShow ssA; + // Complex slideshow, record order doesn't match slide order + private HSLFSlideShow ssB; + + @BeforeEach + void init() throws IOException { + ssA = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); + ssB = HSLFTestDataSamples.getSlideShow("incorrect_slide_order.ppt"); + } + + @AfterEach + void tearDown() throws IOException { + ssA.close(); + ssB.close(); + } + + /** + * Test the simple case - record order matches slide order + */ @Test - void testComplexCase() { - assertEquals(3, ssB.getSlides().size()); - int i=1; - for (HSLFSlide s : ssB.getSlides()) { - assertEquals("Slide "+(i++), HSLFTextParagraph.getRawText(s.getTextParagraphs().get(0))); - } - } - - /** - * Assert that the order of slides is correct. - * - * @param filename - * file name of the slide show to assert - * @param titles - * array of reference slide titles - */ - protected void assertSlideOrdering(String filename, String[] titles) throws IOException { + void testSimpleCase() { + assertEquals(2, ssA.getSlides().size()); + + HSLFSlide s1 = ssA.getSlides().get(0); + HSLFSlide s2 = ssA.getSlides().get(1); + + String[] firstTRs = new String[] { "This is a test title", "This is the title on page 2" }; + + assertEquals(firstTRs[0], HSLFTextParagraph.getRawText(s1.getTextParagraphs().get(0))); + assertEquals(firstTRs[1], HSLFTextParagraph.getRawText(s2.getTextParagraphs().get(0))); + } + + /** + * Test the complex case - record order differs from slide order + */ + @Test + void testComplexCase() { + assertEquals(3, ssB.getSlides().size()); + int i=1; + for (HSLFSlide s : ssB.getSlides()) { + assertEquals("Slide "+(i++), HSLFTextParagraph.getRawText(s.getTextParagraphs().get(0))); + } + } + + /** + * Assert that the order of slides is correct. + * + * @param filename + * file name of the slide show to assert + * @param titles + * array of reference slide titles + */ + protected void assertSlideOrdering(String filename, String[] titles) throws IOException { HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow(filename); - List<HSLFSlide> slide = ppt.getSlides(); + List<HSLFSlide> slide = ppt.getSlides(); - assertEquals(titles.length, slide.size()); - for (int i = 0; i < slide.size(); i++) { - String title = slide.get(i).getTitle(); - assertEquals(titles[i], title, "Wrong slide title in " + filename); - } - ppt.close(); - } + assertEquals(titles.length, slide.size()); + for (int i = 0; i < slide.size(); i++) { + String title = slide.get(i).getTitle(); + assertEquals(titles[i], title, "Wrong slide title in " + filename); + } + ppt.close(); + } @Test - void testTitles() throws Exception { - assertSlideOrdering("basic_test_ppt_file.ppt", new String[] { - "This is a test title", "This is the title on page 2" }); - - assertSlideOrdering("incorrect_slide_order.ppt", new String[] { "Slide 1", - "Slide 2", "Slide 3" }); - - assertSlideOrdering("next_test_ppt_file.ppt", new String[] { - "This is a test title", "This is the title on page 2" }); - - assertSlideOrdering("Single_Coloured_Page.ppt", - new String[] { "This is a title, it" + (char) 0x2019 + "s in black" }); - - assertSlideOrdering("Single_Coloured_Page_With_Fonts_and_Alignments.ppt", - new String[] { "This is a title, it" + (char) 0x2019 + "s in black" }); - - assertSlideOrdering( - "ParagraphStylesShorterThanCharStyles.ppt", - new String[] { - "ROMANCE: AN ANALYSIS", - "AGENDA", - "You are an important supplier of various items that I need", - '\n' + "Although The Psycho set back my relationship process, recovery is luckily enough under way", - "Since the time that we seriously go out together, you rank highly among existing relationships", - "Although our personal interests are mostly compatible, the greatest gap exists in Sex and Shopping", - "Your physical characteristics are strong when compared with your competition", - "The combination of your high physical appearance and personality rank you highly, although your sister is also a top prospect", - "When people found out that we were going out, their responses have been mixed", - "The benchmark of relationship lifecycles, suggests that we are on schedule", - "In summary we can say that we are on the right track, but we must remain aware of possible roadblocks ", - "THE ANSWER", - "Unfortunately a huge disconnect exists between my needs and your existing service", - "SUMMARY", }); - } + void testTitles() throws Exception { + assertSlideOrdering("basic_test_ppt_file.ppt", new String[] { + "This is a test title", "This is the title on page 2" }); + + assertSlideOrdering("incorrect_slide_order.ppt", new String[] { "Slide 1", + "Slide 2", "Slide 3" }); + + assertSlideOrdering("next_test_ppt_file.ppt", new String[] { + "This is a test title", "This is the title on page 2" }); + + assertSlideOrdering("Single_Coloured_Page.ppt", + new String[] { "This is a title, it" + (char) 0x2019 + "s in black" }); + + assertSlideOrdering("Single_Coloured_Page_With_Fonts_and_Alignments.ppt", + new String[] { "This is a title, it" + (char) 0x2019 + "s in black" }); + + assertSlideOrdering( + "ParagraphStylesShorterThanCharStyles.ppt", + new String[] { + "ROMANCE: AN ANALYSIS", + "AGENDA", + "You are an important supplier of various items that I need", + '\n' + "Although The Psycho set back my relationship process, recovery is luckily enough under way", + "Since the time that we seriously go out together, you rank highly among existing relationships", + "Although our personal interests are mostly compatible, the greatest gap exists in Sex and Shopping", + "Your physical characteristics are strong when compared with your competition", + "The combination of your high physical appearance and personality rank you highly, although your sister is also a top prospect", + "When people found out that we were going out, their responses have been mixed", + "The benchmark of relationship lifecycles, suggests that we are on schedule", + "In summary we can say that we are on the right track, but we must remain aware of possible roadblocks ", + "THE ANSWER", + "Unfortunately a huge disconnect exists between my needs and your existing service", + "SUMMARY", }); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTable.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTable.java index 437cb592ff..b02fd31b32 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTable.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTable.java @@ -68,42 +68,42 @@ public class TestTable { @Test void testTable() throws IOException { - try (HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("54111.ppt")) { + try (HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("54111.ppt")) { List<HSLFSlide> slides = ppt.getSlides(); assertEquals(1, slides.size()); checkSlide(slides.get(0)); } - } - - private void checkSlide(final HSLFSlide s) { - List<List<HSLFTextParagraph>> textRuns = s.getTextParagraphs(); - assertEquals(2, textRuns.size()); - - HSLFTextRun textRun = textRuns.get(0).get(0).getTextRuns().get(0); - assertEquals("Table sample", textRun.getRawText().trim()); - assertEquals(1, textRuns.get(0).get(0).getTextRuns().size()); - assertFalse(textRun.getTextParagraph().isBullet()); - - assertEquals("Dummy text", HSLFTextParagraph.getRawText(textRuns.get(1))); - - List<HSLFShape> shapes = s.getShapes(); - assertNotNull(shapes); - assertEquals(3, shapes.size()); - assertTrue(shapes.get(2) instanceof HSLFTable); - final HSLFTable table = (HSLFTable) shapes.get(2); - assertEquals(4, table.getNumberOfColumns()); - assertEquals(6, table.getNumberOfRows()); - for (int x = 0; x < 4; x ++) { + } + + private void checkSlide(final HSLFSlide s) { + List<List<HSLFTextParagraph>> textRuns = s.getTextParagraphs(); + assertEquals(2, textRuns.size()); + + HSLFTextRun textRun = textRuns.get(0).get(0).getTextRuns().get(0); + assertEquals("Table sample", textRun.getRawText().trim()); + assertEquals(1, textRuns.get(0).get(0).getTextRuns().size()); + assertFalse(textRun.getTextParagraph().isBullet()); + + assertEquals("Dummy text", HSLFTextParagraph.getRawText(textRuns.get(1))); + + List<HSLFShape> shapes = s.getShapes(); + assertNotNull(shapes); + assertEquals(3, shapes.size()); + assertTrue(shapes.get(2) instanceof HSLFTable); + final HSLFTable table = (HSLFTable) shapes.get(2); + assertEquals(4, table.getNumberOfColumns()); + assertEquals(6, table.getNumberOfRows()); + for (int x = 0; x < 4; x ++) { HSLFTableCell c = table.getCell(0, x); assertNotNull(c); - assertEquals("TH Cell " + (x + 1), HSLFTextParagraph.getRawText(c.getTextParagraphs())); - for (int y = 1; y < 6; y++) { - c = table.getCell(y, x); - assertNotNull(c); - assertEquals("Row " + y + ", Cell " + (x + 1), c.getText()); - } - } - } + assertEquals("TH Cell " + (x + 1), HSLFTextParagraph.getRawText(c.getTextParagraphs())); + for (int y = 1; y < 6; y++) { + c = table.getCell(y, x); + assertNotNull(c); + assertEquals("Row " + y + ", Cell " + (x + 1), c.getText()); + } + } + } @Test void testAddText() throws IOException { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java index 6fc4dc6030..0079c348dc 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java @@ -43,124 +43,124 @@ import org.junit.jupiter.api.Test; */ @SuppressWarnings("UnusedAssignment") public final class TestTextRun { - // SlideShow primed on the test data - private HSLFSlideShow ss; - private HSLFSlideShow ssRich; - - @BeforeEach - void setUp() throws IOException { - // Basic (non rich) test file - ss = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); - - // Rich test file - ssRich = HSLFTestDataSamples.getSlideShow("Single_Coloured_Page.ppt"); - } - - @AfterEach - void tearDown() throws IOException { - ssRich.close(); - ss.close(); - } - - /** - * Test to ensure that getting the text works correctly - */ - @Test - void testGetText() { - HSLFSlide slideOne = ss.getSlides().get(0); - List<List<HSLFTextParagraph>> textParas = slideOne.getTextParagraphs(); - - assertEquals(2, textParas.size()); - - // Get text works with \n - assertEquals("This is a test title", HSLFTextParagraph.getText(textParas.get(0))); - assertEquals("This is a test subtitle\nThis is on page 1", HSLFTextParagraph.getText(textParas.get(1))); - - // Raw text has \r instead - assertEquals("This is a test title", HSLFTextParagraph.getRawText(textParas.get(0))); - assertEquals("This is a test subtitle\rThis is on page 1", HSLFTextParagraph.getRawText(textParas.get(1))); - - - // Now check on a rich text run - HSLFSlide slideOneR = ssRich.getSlides().get(0); - textParas = slideOneR.getTextParagraphs(); - - assertEquals(2, textParas.size()); - assertEquals("This is a title, it\u2019s in black", HSLFTextParagraph.getText(textParas.get(0))); - assertEquals("This is the subtitle, in bold\nThis bit is blue and italic\nThis bit is red (normal)", HSLFTextParagraph.getText(textParas.get(1))); - assertEquals("This is a title, it\u2019s in black", HSLFTextParagraph.getRawText(textParas.get(0))); - assertEquals("This is the subtitle, in bold\rThis bit is blue and italic\rThis bit is red (normal)", HSLFTextParagraph.getRawText(textParas.get(1))); - } - - /** - * Test to ensure changing non rich text bytes->bytes works correctly - */ - @Test - void testSetText() { - HSLFSlide slideOne = ss.getSlides().get(0); - List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs(); - HSLFTextParagraph run = textRuns.get(0).get(0); - HSLFTextRun tr = run.getTextRuns().get(0); - - // Check current text - assertEquals("This is a test title", tr.getRawText()); - - // Change - String changeTo = "New test title"; - tr.setText(changeTo); - assertEquals(changeTo, tr.getRawText()); - - // Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r' - tr.setText(changeTo + "\n"); - assertEquals(changeTo + "\r", tr.getRawText()); - } - - /** - * Test to ensure that changing non rich text between bytes and - * chars works correctly - */ - @SuppressWarnings("unused") + // SlideShow primed on the test data + private HSLFSlideShow ss; + private HSLFSlideShow ssRich; + + @BeforeEach + void setUp() throws IOException { + // Basic (non rich) test file + ss = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt"); + + // Rich test file + ssRich = HSLFTestDataSamples.getSlideShow("Single_Coloured_Page.ppt"); + } + + @AfterEach + void tearDown() throws IOException { + ssRich.close(); + ss.close(); + } + + /** + * Test to ensure that getting the text works correctly + */ + @Test + void testGetText() { + HSLFSlide slideOne = ss.getSlides().get(0); + List<List<HSLFTextParagraph>> textParas = slideOne.getTextParagraphs(); + + assertEquals(2, textParas.size()); + + // Get text works with \n + assertEquals("This is a test title", HSLFTextParagraph.getText(textParas.get(0))); + assertEquals("This is a test subtitle\nThis is on page 1", HSLFTextParagraph.getText(textParas.get(1))); + + // Raw text has \r instead + assertEquals("This is a test title", HSLFTextParagraph.getRawText(textParas.get(0))); + assertEquals("This is a test subtitle\rThis is on page 1", HSLFTextParagraph.getRawText(textParas.get(1))); + + + // Now check on a rich text run + HSLFSlide slideOneR = ssRich.getSlides().get(0); + textParas = slideOneR.getTextParagraphs(); + + assertEquals(2, textParas.size()); + assertEquals("This is a title, it\u2019s in black", HSLFTextParagraph.getText(textParas.get(0))); + assertEquals("This is the subtitle, in bold\nThis bit is blue and italic\nThis bit is red (normal)", HSLFTextParagraph.getText(textParas.get(1))); + assertEquals("This is a title, it\u2019s in black", HSLFTextParagraph.getRawText(textParas.get(0))); + assertEquals("This is the subtitle, in bold\rThis bit is blue and italic\rThis bit is red (normal)", HSLFTextParagraph.getRawText(textParas.get(1))); + } + + /** + * Test to ensure changing non rich text bytes->bytes works correctly + */ + @Test + void testSetText() { + HSLFSlide slideOne = ss.getSlides().get(0); + List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs(); + HSLFTextParagraph run = textRuns.get(0).get(0); + HSLFTextRun tr = run.getTextRuns().get(0); + + // Check current text + assertEquals("This is a test title", tr.getRawText()); + + // Change + String changeTo = "New test title"; + tr.setText(changeTo); + assertEquals(changeTo, tr.getRawText()); + + // Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r' + tr.setText(changeTo + "\n"); + assertEquals(changeTo + "\r", tr.getRawText()); + } + + /** + * Test to ensure that changing non rich text between bytes and + * chars works correctly + */ + @SuppressWarnings("unused") @Test - void testAdvancedSetText() { - HSLFSlide slideOne = ss.getSlides().get(0); - List<HSLFTextParagraph> paras = slideOne.getTextParagraphs().get(0); - HSLFTextParagraph para = paras.get(0); + void testAdvancedSetText() { + HSLFSlide slideOne = ss.getSlides().get(0); + List<HSLFTextParagraph> paras = slideOne.getTextParagraphs().get(0); + HSLFTextParagraph para = paras.get(0); TextHeaderAtom tha = null; TextBytesAtom tba = null; TextCharsAtom tca = null; - for ( org.apache.poi.hslf.record.Record r : para.getRecords()) { - if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r; - else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r; - else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r; - } - - // Bytes -> Bytes - assertNull(tca); - assertNotNull(tba); - // assertFalse(run._isUnicode); - assertEquals("This is a test title", para.getTextRuns().get(0).getRawText()); - - String changeBytesOnly = "New Test Title"; - HSLFTextParagraph.setText(paras, changeBytesOnly); - para = paras.get(0); - tha = null; tba = null; tca = null; for ( org.apache.poi.hslf.record.Record r : para.getRecords()) { if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r; else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r; else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r; } - assertEquals(changeBytesOnly, HSLFTextParagraph.getRawText(paras)); - assertNull(tca); - assertNotNull(tba); + // Bytes -> Bytes + assertNull(tca); + assertNotNull(tba); + // assertFalse(run._isUnicode); + assertEquals("This is a test title", para.getTextRuns().get(0).getRawText()); - // Bytes -> Chars - assertEquals(changeBytesOnly, HSLFTextParagraph.getRawText(paras)); + String changeBytesOnly = "New Test Title"; + HSLFTextParagraph.setText(paras, changeBytesOnly); + para = paras.get(0); + tha = null; tba = null; tca = null; + for ( org.apache.poi.hslf.record.Record r : para.getRecords()) { + if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r; + else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r; + else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r; + } + + assertEquals(changeBytesOnly, HSLFTextParagraph.getRawText(paras)); + assertNull(tca); + assertNotNull(tba); + + // Bytes -> Chars + assertEquals(changeBytesOnly, HSLFTextParagraph.getRawText(paras)); - String changeByteChar = "This is a test title with a '\u0121' g with a dot"; - HSLFTextParagraph.setText(paras, changeByteChar); - para = paras.get(0); + String changeByteChar = "This is a test title with a '\u0121' g with a dot"; + HSLFTextParagraph.setText(paras, changeByteChar); + para = paras.get(0); tha = null; tba = null; tca = null; for ( org.apache.poi.hslf.record.Record r : para.getRecords()) { if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r; @@ -168,16 +168,16 @@ public final class TestTextRun { else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r; } - assertEquals(changeByteChar, HSLFTextParagraph.getRawText(paras)); - assertNotNull(tca); - assertNull(tba); + assertEquals(changeByteChar, HSLFTextParagraph.getRawText(paras)); + assertNotNull(tca); + assertNull(tba); - // Chars -> Chars - assertNotNull(tca); - assertEquals(changeByteChar, HSLFTextParagraph.getRawText(paras)); + // Chars -> Chars + assertNotNull(tca); + assertEquals(changeByteChar, HSLFTextParagraph.getRawText(paras)); - String changeCharChar = "This is a test title with a '\u0147' N with a hat"; - HSLFTextParagraph.setText(paras, changeCharChar); + String changeCharChar = "This is a test title with a '\u0147' N with a hat"; + HSLFTextParagraph.setText(paras, changeCharChar); para = paras.get(0); tha = null; tba = null; tca = null; for ( org.apache.poi.hslf.record.Record r : para.getRecords()) { @@ -186,334 +186,334 @@ public final class TestTextRun { else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r; } - assertEquals(changeCharChar, HSLFTextParagraph.getRawText(paras)); - assertNotNull(tca); - assertNull(tba); - } + assertEquals(changeCharChar, HSLFTextParagraph.getRawText(paras)); + assertNotNull(tca); + assertNull(tba); + } - /** - * Tests to ensure that non rich text has the right default rich text run - * set up for it - */ - @Test - void testGetRichTextNonRich() { - HSLFSlide slideOne = ss.getSlides().get(0); - List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); + /** + * Tests to ensure that non rich text has the right default rich text run + * set up for it + */ + @Test + void testGetRichTextNonRich() { + HSLFSlide slideOne = ss.getSlides().get(0); + List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); - assertEquals(2, textParass.size()); + assertEquals(2, textParass.size()); - List<HSLFTextParagraph> trA = textParass.get(0); - List<HSLFTextParagraph> trB = textParass.get(1); + List<HSLFTextParagraph> trA = textParass.get(0); + List<HSLFTextParagraph> trB = textParass.get(1); - assertEquals(1, trA.size()); - assertEquals(2, trB.size()); + assertEquals(1, trA.size()); + assertEquals(2, trB.size()); - HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0); - HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); + HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0); + HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); - assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText()); - assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText()); - } + assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText()); + assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText()); + } - /** - * Tests to ensure that the rich text runs are built up correctly - */ - @Test - void testGetRichText() { - HSLFSlide slideOne = ssRich.getSlides().get(0); - List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); + /** + * Tests to ensure that the rich text runs are built up correctly + */ + @Test + void testGetRichText() { + HSLFSlide slideOne = ssRich.getSlides().get(0); + List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); - assertEquals(2, textParass.size()); + assertEquals(2, textParass.size()); - List<HSLFTextParagraph> trA = textParass.get(0); - List<HSLFTextParagraph> trB = textParass.get(1); + List<HSLFTextParagraph> trA = textParass.get(0); + List<HSLFTextParagraph> trB = textParass.get(1); - assertEquals(1, trA.size()); - assertEquals(3, trB.size()); + assertEquals(1, trA.size()); + assertEquals(3, trB.size()); - HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0); - HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); - HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); - HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0); + HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0); + HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); + HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); + HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0); - assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText()); + assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText()); - String trBstr = HSLFTextParagraph.getRawText(trB); - assertEquals(trBstr.substring(0, 30), rtrB.getRawText()); - assertEquals(trBstr.substring(30,58), rtrC.getRawText()); - assertEquals(trBstr.substring(58,82), rtrD.getRawText()); + String trBstr = HSLFTextParagraph.getRawText(trB); + assertEquals(trBstr.substring(0, 30), rtrB.getRawText()); + assertEquals(trBstr.substring(30,58), rtrC.getRawText()); + assertEquals(trBstr.substring(58,82), rtrD.getRawText()); - // Same paragraph styles - assertEquals(trB.get(0).getParagraphStyle(), trB.get(1).getParagraphStyle()); - assertEquals(trB.get(0).getParagraphStyle(), trB.get(2).getParagraphStyle()); + // Same paragraph styles + assertEquals(trB.get(0).getParagraphStyle(), trB.get(1).getParagraphStyle()); + assertEquals(trB.get(0).getParagraphStyle(), trB.get(2).getParagraphStyle()); - // Different char styles - assertNotEquals(rtrB.getCharacterStyle(), rtrC.getCharacterStyle()); + // Different char styles + assertNotEquals(rtrB.getCharacterStyle(), rtrC.getCharacterStyle()); assertNotEquals(rtrB.getCharacterStyle(), rtrD.getCharacterStyle()); assertNotEquals(rtrC.getCharacterStyle(), rtrD.getCharacterStyle()); - } - - /** - * Tests to ensure that setting the text where the text isn't rich, - * ensuring that everything stays with the same default styling - */ - @Test - void testSetTextWhereNotRich() { - HSLFSlide slideOne = ss.getSlides().get(0); - List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); - List<HSLFTextParagraph> trB = textParass.get(0); - assertEquals(1, trB.size()); - - HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); - assertEquals(HSLFTextParagraph.getText(trB), rtrB.getRawText()); - - // Change text via normal - HSLFTextParagraph.setText(trB, "Test Foo Test"); - rtrB = trB.get(0).getTextRuns().get(0); - assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB)); - assertEquals("Test Foo Test", rtrB.getRawText()); - } - - /** - * Tests to ensure that setting the text where the text is rich - * sets everything to the same styling - */ - @Test - void testSetTextWhereRich() { - HSLFSlide slideOne = ssRich.getSlides().get(0); - List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); - List<HSLFTextParagraph> trB = textParass.get(1); - assertEquals(3, trB.size()); - - HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); - HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); - HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0); - TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle(); - TextPropCollection tpBC = rtrB.getCharacterStyle(); - TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle(); - TextPropCollection tpCC = rtrC.getCharacterStyle(); - TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle(); - TextPropCollection tpDC = rtrD.getCharacterStyle(); - -// assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText()); - assertNotNull(tpBP); - assertNotNull(tpBC); - assertNotNull(tpCP); - assertNotNull(tpCC); - assertNotNull(tpDP); - assertNotNull(tpDC); - assertEquals(tpBP,tpCP); - assertEquals(tpBP,tpDP); - assertEquals(tpCP,tpDP); - assertNotEquals(tpBC,tpCC); - assertNotEquals(tpBC,tpDC); - assertNotEquals(tpCC,tpDC); - - // Change text via normal - HSLFTextParagraph.setText(trB, "Test Foo Test"); - - // Ensure now have first style - assertEquals(1, trB.get(0).getTextRuns().size()); - rtrB = trB.get(0).getTextRuns().get(0); - assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB)); - assertEquals("Test Foo Test", rtrB.getRawText()); - assertNotNull(rtrB.getCharacterStyle()); - assertNotNull(rtrB.getTextParagraph().getParagraphStyle()); - assertEquals( tpBP, rtrB.getTextParagraph().getParagraphStyle() ); - assertEquals( tpBC, rtrB.getCharacterStyle() ); - } - - /** - * Test to ensure the right stuff happens if we change the text - * in a rich text run, that doesn't happen to actually be rich - */ - @Test - void testChangeTextInRichTextRunNonRich() { - HSLFSlide slideOne = ss.getSlides().get(0); - List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs(); - List<HSLFTextParagraph> trB = textRuns.get(1); - assertEquals(1, trB.get(0).getTextRuns().size()); - - HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); - assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText()); - assertNotNull(rtrB.getCharacterStyle()); - assertNotNull(rtrB.getTextParagraph().getParagraphStyle()); - - // Change text via rich - rtrB.setText("Test Test Test"); - assertEquals("Test Test Test", HSLFTextParagraph.getRawText(trB.subList(0, 1))); - assertEquals("Test Test Test", rtrB.getRawText()); - - // Will now have dummy props + } + + /** + * Tests to ensure that setting the text where the text isn't rich, + * ensuring that everything stays with the same default styling + */ + @Test + void testSetTextWhereNotRich() { + HSLFSlide slideOne = ss.getSlides().get(0); + List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); + List<HSLFTextParagraph> trB = textParass.get(0); + assertEquals(1, trB.size()); + + HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); + assertEquals(HSLFTextParagraph.getText(trB), rtrB.getRawText()); + + // Change text via normal + HSLFTextParagraph.setText(trB, "Test Foo Test"); + rtrB = trB.get(0).getTextRuns().get(0); + assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB)); + assertEquals("Test Foo Test", rtrB.getRawText()); + } + + /** + * Tests to ensure that setting the text where the text is rich + * sets everything to the same styling + */ + @Test + void testSetTextWhereRich() { + HSLFSlide slideOne = ssRich.getSlides().get(0); + List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); + List<HSLFTextParagraph> trB = textParass.get(1); + assertEquals(3, trB.size()); + + HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); + HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); + HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0); + TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle(); + TextPropCollection tpBC = rtrB.getCharacterStyle(); + TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle(); + TextPropCollection tpCC = rtrC.getCharacterStyle(); + TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle(); + TextPropCollection tpDC = rtrD.getCharacterStyle(); + +// assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText()); + assertNotNull(tpBP); + assertNotNull(tpBC); + assertNotNull(tpCP); + assertNotNull(tpCC); + assertNotNull(tpDP); + assertNotNull(tpDC); + assertEquals(tpBP,tpCP); + assertEquals(tpBP,tpDP); + assertEquals(tpCP,tpDP); + assertNotEquals(tpBC,tpCC); + assertNotEquals(tpBC,tpDC); + assertNotEquals(tpCC,tpDC); + + // Change text via normal + HSLFTextParagraph.setText(trB, "Test Foo Test"); + + // Ensure now have first style + assertEquals(1, trB.get(0).getTextRuns().size()); + rtrB = trB.get(0).getTextRuns().get(0); + assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB)); + assertEquals("Test Foo Test", rtrB.getRawText()); assertNotNull(rtrB.getCharacterStyle()); assertNotNull(rtrB.getTextParagraph().getParagraphStyle()); - } - - /** - * Tests to ensure changing the text within rich text runs works - * correctly - */ - @Test - void testChangeTextInRichTextRun() { - HSLFSlide slideOne = ssRich.getSlides().get(0); - List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); - List<HSLFTextParagraph> trB = textParass.get(1); - assertEquals(3, trB.size()); - - // We start with 3 text runs, each with their own set of styles, - // but all sharing the same paragraph styles - HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); - HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); - HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0); - TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle(); - TextPropCollection tpBC = rtrB.getCharacterStyle(); - TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle(); - TextPropCollection tpCC = rtrC.getCharacterStyle(); - TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle(); - TextPropCollection tpDC = rtrD.getCharacterStyle(); - - // Check text and stylings - assertEquals(HSLFTextParagraph.getRawText(trB).substring(0, 30), rtrB.getRawText()); - assertNotNull(tpBP); - assertNotNull(tpBC); - assertNotNull(tpCP); - assertNotNull(tpCC); - assertNotNull(tpDP); - assertNotNull(tpDC); - assertEquals(tpBP, tpCP); - assertEquals(tpBP, tpDP); - assertEquals(tpCP, tpDP); - assertNotEquals(tpBC, tpCC); - assertNotEquals(tpBC, tpDC); - assertNotEquals(tpCC, tpDC); - - // Check text in the rich runs - assertEquals("This is the subtitle, in bold\r", rtrB.getRawText()); - assertEquals("This bit is blue and italic\r", rtrC.getRawText()); - assertEquals("This bit is red (normal)", rtrD.getRawText()); - - String newBText = "New Subtitle, will still be bold\n"; - String newCText = "New blue and italic text\n"; - String newDText = "Funky new normal red text"; - rtrB.setText(newBText); - rtrC.setText(newCText); - rtrD.setText(newDText); - HSLFTextParagraph.storeText(trB); - - assertEquals(newBText.replace('\n','\r'), rtrB.getRawText()); - assertEquals(newCText.replace('\n','\r'), rtrC.getRawText()); - assertEquals(newDText.replace('\n','\r'), rtrD.getRawText()); - - assertEquals(newBText.replace('\n','\r') + newCText.replace('\n','\r') + newDText.replace('\n','\r'), HSLFTextParagraph.getRawText(trB)); - - // The styles should have been updated for the new sizes - assertEquals(newBText.length(), tpBC.getCharactersCovered()); - assertEquals(newCText.length(), tpCC.getCharactersCovered()); - assertEquals(newDText.length()+1, tpDC.getCharactersCovered()); // Last one is always one larger + assertEquals( tpBP, rtrB.getTextParagraph().getParagraphStyle() ); + assertEquals( tpBC, rtrB.getCharacterStyle() ); + } + + /** + * Test to ensure the right stuff happens if we change the text + * in a rich text run, that doesn't happen to actually be rich + */ + @Test + void testChangeTextInRichTextRunNonRich() { + HSLFSlide slideOne = ss.getSlides().get(0); + List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs(); + List<HSLFTextParagraph> trB = textRuns.get(1); + assertEquals(1, trB.get(0).getTextRuns().size()); + + HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); + assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText()); + assertNotNull(rtrB.getCharacterStyle()); + assertNotNull(rtrB.getTextParagraph().getParagraphStyle()); + + // Change text via rich + rtrB.setText("Test Test Test"); + assertEquals("Test Test Test", HSLFTextParagraph.getRawText(trB.subList(0, 1))); + assertEquals("Test Test Test", rtrB.getRawText()); + + // Will now have dummy props + assertNotNull(rtrB.getCharacterStyle()); + assertNotNull(rtrB.getTextParagraph().getParagraphStyle()); + } + + /** + * Tests to ensure changing the text within rich text runs works + * correctly + */ + @Test + void testChangeTextInRichTextRun() { + HSLFSlide slideOne = ssRich.getSlides().get(0); + List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs(); + List<HSLFTextParagraph> trB = textParass.get(1); + assertEquals(3, trB.size()); + + // We start with 3 text runs, each with their own set of styles, + // but all sharing the same paragraph styles + HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0); + HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0); + HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0); + TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle(); + TextPropCollection tpBC = rtrB.getCharacterStyle(); + TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle(); + TextPropCollection tpCC = rtrC.getCharacterStyle(); + TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle(); + TextPropCollection tpDC = rtrD.getCharacterStyle(); + + // Check text and stylings + assertEquals(HSLFTextParagraph.getRawText(trB).substring(0, 30), rtrB.getRawText()); + assertNotNull(tpBP); + assertNotNull(tpBC); + assertNotNull(tpCP); + assertNotNull(tpCC); + assertNotNull(tpDP); + assertNotNull(tpDC); + assertEquals(tpBP, tpCP); + assertEquals(tpBP, tpDP); + assertEquals(tpCP, tpDP); + assertNotEquals(tpBC, tpCC); + assertNotEquals(tpBC, tpDC); + assertNotEquals(tpCC, tpDC); + + // Check text in the rich runs + assertEquals("This is the subtitle, in bold\r", rtrB.getRawText()); + assertEquals("This bit is blue and italic\r", rtrC.getRawText()); + assertEquals("This bit is red (normal)", rtrD.getRawText()); + + String newBText = "New Subtitle, will still be bold\n"; + String newCText = "New blue and italic text\n"; + String newDText = "Funky new normal red text"; + rtrB.setText(newBText); + rtrC.setText(newCText); + rtrD.setText(newDText); + HSLFTextParagraph.storeText(trB); + + assertEquals(newBText.replace('\n','\r'), rtrB.getRawText()); + assertEquals(newCText.replace('\n','\r'), rtrC.getRawText()); + assertEquals(newDText.replace('\n','\r'), rtrD.getRawText()); + + assertEquals(newBText.replace('\n','\r') + newCText.replace('\n','\r') + newDText.replace('\n','\r'), HSLFTextParagraph.getRawText(trB)); + + // The styles should have been updated for the new sizes + assertEquals(newBText.length(), tpBC.getCharactersCovered()); + assertEquals(newCText.length(), tpCC.getCharactersCovered()); + assertEquals(newDText.length()+1, tpDC.getCharactersCovered()); // Last one is always one larger // Paragraph style should be sum of text length - assertEquals( - newBText.length() + newCText.length() + newDText.length() +1, - tpBP.getCharactersCovered() + tpCP.getCharactersCovered() + tpDP.getCharactersCovered() - ); - - // Check stylings still as expected - TextPropCollection ntpBC = rtrB.getCharacterStyle(); - TextPropCollection ntpCC = rtrC.getCharacterStyle(); - TextPropCollection ntpDC = rtrD.getCharacterStyle(); - assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList()); - assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList()); - assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList()); - } - - - /** - * Test case for Bug 41015. - * - * In some cases RichTextRun.getText() threw StringIndexOutOfBoundsException because - * of the wrong list of potential paragraph properties defined in StyleTextPropAtom. - * - */ - @Test - void testBug41015() throws IOException { - List<HSLFTextRun> rt; - - HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("bug-41015.ppt"); - HSLFSlide sl = ppt.getSlides().get(0); + assertEquals( + newBText.length() + newCText.length() + newDText.length() +1, + tpBP.getCharactersCovered() + tpCP.getCharactersCovered() + tpDP.getCharactersCovered() + ); + + // Check stylings still as expected + TextPropCollection ntpBC = rtrB.getCharacterStyle(); + TextPropCollection ntpCC = rtrC.getCharacterStyle(); + TextPropCollection ntpDC = rtrD.getCharacterStyle(); + assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList()); + assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList()); + assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList()); + } + + + /** + * Test case for Bug 41015. + * + * In some cases RichTextRun.getText() threw StringIndexOutOfBoundsException because + * of the wrong list of potential paragraph properties defined in StyleTextPropAtom. + * + */ + @Test + void testBug41015() throws IOException { + List<HSLFTextRun> rt; + + HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("bug-41015.ppt"); + HSLFSlide sl = ppt.getSlides().get(0); List<List<HSLFTextParagraph>> textParass = sl.getTextParagraphs(); - assertEquals(2, textParass.size()); + assertEquals(2, textParass.size()); - List<HSLFTextParagraph> textParas = textParass.get(0); - rt = textParass.get(0).get(0).getTextRuns(); - assertEquals(1, rt.size()); - assertEquals(0, textParass.get(0).get(0).getIndentLevel()); - assertEquals("sdfsdfsdf", rt.get(0).getRawText()); + List<HSLFTextParagraph> textParas = textParass.get(0); + rt = textParass.get(0).get(0).getTextRuns(); + assertEquals(1, rt.size()); + assertEquals(0, textParass.get(0).get(0).getIndentLevel()); + assertEquals("sdfsdfsdf", rt.get(0).getRawText()); - textParas = textParass.get(1); + textParas = textParass.get(1); String[] texts = {"Sdfsdfsdf\r", "Dfgdfg\r", "Dfgdfgdfg\r", "Sdfsdfs\r", "Sdfsdf\r"}; int[] indents = {0, 0, 0, 1, 1}; - int i=0; - for (HSLFTextParagraph p : textParas) { - assertEquals(texts[i], p.getTextRuns().get(0).getRawText()); - assertEquals(indents[i], p.getIndentLevel()); - i++; - } - ppt.close(); - } - - /** - * Test creation of TextRun objects. - */ - @Test - void testAddTextRun() throws IOException { - HSLFSlideShow ppt = new HSLFSlideShow(); - HSLFSlide slide = ppt.createSlide(); - - assertEquals(0, slide.getTextParagraphs().size()); - - HSLFTextBox shape1 = new HSLFTextBox(); - List<HSLFTextParagraph> run1 = shape1.getTextParagraphs(); - shape1.setText("Text 1"); - slide.addShape(shape1); - - //The array of Slide's text runs must be updated when new text shapes are added. - List<List<HSLFTextParagraph>> runs = slide.getTextParagraphs(); - assertNotNull(runs); - assertSame(run1, runs.get(0)); - - HSLFTextBox shape2 = new HSLFTextBox(); - List<HSLFTextParagraph> run2 = shape2.getTextParagraphs(); - shape2.setText("Text 2"); - slide.addShape(shape2); - - runs = slide.getTextParagraphs(); - assertEquals(2, runs.size()); - - assertSame(run1, runs.get(0)); - assertSame(run2, runs.get(1)); - - // as getShapes() - List<HSLFShape> sh = slide.getShapes(); - assertEquals(2, sh.size()); - assertTrue(sh.get(0) instanceof HSLFTextBox); - HSLFTextBox box1 = (HSLFTextBox)sh.get(0); - assertSame(run1, box1.getTextParagraphs()); - HSLFTextBox box2 = (HSLFTextBox)sh.get(1); - assertSame(run2, box2.getTextParagraphs()); - - // test Table - a complex group of shapes containing text objects - HSLFSlide slide2 = ppt.createSlide(); - assertTrue(slide2.getTextParagraphs().isEmpty()); - HSLFTable table = new HSLFTable(2, 2); - slide2.addShape(table); - runs = slide2.getTextParagraphs(); - assertNotNull(runs); - assertEquals(4, runs.size()); - ppt.close(); - } - - @Test - void test48916() throws IOException { + int i=0; + for (HSLFTextParagraph p : textParas) { + assertEquals(texts[i], p.getTextRuns().get(0).getRawText()); + assertEquals(indents[i], p.getIndentLevel()); + i++; + } + ppt.close(); + } + + /** + * Test creation of TextRun objects. + */ + @Test + void testAddTextRun() throws IOException { + HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlide slide = ppt.createSlide(); + + assertEquals(0, slide.getTextParagraphs().size()); + + HSLFTextBox shape1 = new HSLFTextBox(); + List<HSLFTextParagraph> run1 = shape1.getTextParagraphs(); + shape1.setText("Text 1"); + slide.addShape(shape1); + + //The array of Slide's text runs must be updated when new text shapes are added. + List<List<HSLFTextParagraph>> runs = slide.getTextParagraphs(); + assertNotNull(runs); + assertSame(run1, runs.get(0)); + + HSLFTextBox shape2 = new HSLFTextBox(); + List<HSLFTextParagraph> run2 = shape2.getTextParagraphs(); + shape2.setText("Text 2"); + slide.addShape(shape2); + + runs = slide.getTextParagraphs(); + assertEquals(2, runs.size()); + + assertSame(run1, runs.get(0)); + assertSame(run2, runs.get(1)); + + // as getShapes() + List<HSLFShape> sh = slide.getShapes(); + assertEquals(2, sh.size()); + assertTrue(sh.get(0) instanceof HSLFTextBox); + HSLFTextBox box1 = (HSLFTextBox)sh.get(0); + assertSame(run1, box1.getTextParagraphs()); + HSLFTextBox box2 = (HSLFTextBox)sh.get(1); + assertSame(run2, box2.getTextParagraphs()); + + // test Table - a complex group of shapes containing text objects + HSLFSlide slide2 = ppt.createSlide(); + assertTrue(slide2.getTextParagraphs().isEmpty()); + HSLFTable table = new HSLFTable(2, 2); + slide2.addShape(table); + runs = slide2.getTextParagraphs(); + assertNotNull(runs); + assertEquals(4, runs.size()); + ppt.close(); + } + + @Test + void test48916() throws IOException { HSLFSlideShow ppt1 = HSLFTestDataSamples.getSlideShow("SampleShow.ppt"); List<HSLFSlide> slides = ppt1.getSlides(); for(HSLFSlide slide : slides){ @@ -555,8 +555,8 @@ public final class TestTextRun { ppt1.close(); } - @Test - void test52244() throws IOException { + @Test + void test52244() throws IOException { HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("52244.ppt"); HSLFSlide slide = ppt.getSlides().get(0); @@ -564,7 +564,7 @@ public final class TestTextRun { int i=0; for (List<HSLFTextParagraph> textParas : slide.getTextParagraphs()) { - HSLFTextRun first = textParas.get(0).getTextRuns().get(0); + HSLFTextRun first = textParas.get(0).getTextRuns().get(0); assertEquals("Arial", first.getFontFamily()); assertNotNull(first.getFontSize()); assertEquals(sizes[i++], first.getFontSize().intValue()); @@ -572,15 +572,15 @@ public final class TestTextRun { ppt.close(); } - @Test - void testAppendEmpty() throws IOException { + @Test + void testAppendEmpty() throws IOException { try (HSLFSlideShow ppt = new HSLFSlideShow()) { - HSLFSlide s = ppt.createSlide(); - HSLFTextBox title = s.addTitle(); - title.setText(""); - title.appendText("\n", true); - title.appendText("para", true); - assertEquals("\npara", title.getText()); - } - } + HSLFSlide s = ppt.createSlide(); + HSLFTextBox title = s.addTitle(); + title.setText(""); + title.appendText("\n", true); + title.appendText("para", true); + assertEquals("\npara", title.getText()); + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/util/TestSystemTimeUtils.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/util/TestSystemTimeUtils.java index ba67d2170f..ca3a920de5 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/util/TestSystemTimeUtils.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/util/TestSystemTimeUtils.java @@ -32,19 +32,19 @@ import org.junit.jupiter.api.Test; * Tests that SystemTimeUtils works properly. */ public final class TestSystemTimeUtils { - // From real files - private final byte[] data_a = new byte[] { - 0xD6-256, 07, 01, 00, - 02, 00, 0x18, 00, 0x0A, 00, 0x1A, 00, - 0x0F, 00, 0xCD-256, 00 - }; - private final byte[] data_b = new byte[] { - 00, 00, 0xE1-256, 0x2E, 0x1C, 00, 00, 00, - 01, 00, 00, 00, 0xD6-256, 0x07, 01, 00, - 02, 00, 0x18, 00, 0x15, 00, 0x19, 00, 03, - 00, 0xD5-256, 02, 0x0A, 00, 00, 00, - 0x0A, 00, 00, 00 - }; + // From real files + private final byte[] data_a = new byte[] { + 0xD6-256, 07, 01, 00, + 02, 00, 0x18, 00, 0x0A, 00, 0x1A, 00, + 0x0F, 00, 0xCD-256, 00 + }; + private final byte[] data_b = new byte[] { + 00, 00, 0xE1-256, 0x2E, 0x1C, 00, 00, 00, + 01, 00, 00, 00, 0xD6-256, 0x07, 01, 00, + 02, 00, 0x18, 00, 0x15, 00, 0x19, 00, 03, + 00, 0xD5-256, 02, 0x0A, 00, 00, 00, + 0x0A, 00, 00, 00 + }; private static SimpleDateFormat sdf; @@ -54,49 +54,49 @@ public final class TestSystemTimeUtils { sdf.setTimeZone(LocaleUtil.getUserTimeZone()); } - @Test + @Test void testGetDateA() throws Exception { - Date date = SystemTimeUtils.getDate(data_a); - - // Is 2006-01-24 (2nd day of week) 10:26:15.205 - Date exp = sdf.parse("2006-01-24 10:26:15.205"); - assertEquals(exp.getTime(), date.getTime()); - assertEquals(exp, date); - } - - @Test - void testGetDateB() throws Exception { - Date date = SystemTimeUtils.getDate(data_b, 8+4); - - // Is 2006-01-24 (2nd day of week) 21:25:03.725 - Date exp = sdf.parse("2006-01-24 21:25:03.725"); - assertEquals(exp.getTime(), date.getTime()); - assertEquals(exp, date); - } - - @Test - void testWriteDateA() throws Exception { - byte[] out_a = new byte[data_a.length]; - Date date = sdf.parse("2006-01-24 10:26:15.205"); - SystemTimeUtils.storeDate(date, out_a); - - for(int i=0; i<out_a.length; i++) { - assertEquals(data_a[i], out_a[i]); - } - } - - @Test - void testWriteDateB() throws Exception { - byte[] out_b = new byte[data_b.length]; - // Copy over start and end, ignoring the 16 byte date field in the middle - System.arraycopy(data_b, 0, out_b, 0, 12); - System.arraycopy(data_b, 12+16, out_b, 12+16, data_b.length-12-16); - - Date date = sdf.parse("2006-01-24 21:25:03.725"); - SystemTimeUtils.storeDate(date, out_b, 12); - - for(int i=0; i<out_b.length; i++) { - assertEquals(data_b[i], out_b[i]); - } - } + Date date = SystemTimeUtils.getDate(data_a); + + // Is 2006-01-24 (2nd day of week) 10:26:15.205 + Date exp = sdf.parse("2006-01-24 10:26:15.205"); + assertEquals(exp.getTime(), date.getTime()); + assertEquals(exp, date); + } + + @Test + void testGetDateB() throws Exception { + Date date = SystemTimeUtils.getDate(data_b, 8+4); + + // Is 2006-01-24 (2nd day of week) 21:25:03.725 + Date exp = sdf.parse("2006-01-24 21:25:03.725"); + assertEquals(exp.getTime(), date.getTime()); + assertEquals(exp, date); + } + + @Test + void testWriteDateA() throws Exception { + byte[] out_a = new byte[data_a.length]; + Date date = sdf.parse("2006-01-24 10:26:15.205"); + SystemTimeUtils.storeDate(date, out_a); + + for(int i=0; i<out_a.length; i++) { + assertEquals(data_a[i], out_a[i]); + } + } + + @Test + void testWriteDateB() throws Exception { + byte[] out_b = new byte[data_b.length]; + // Copy over start and end, ignoring the 16 byte date field in the middle + System.arraycopy(data_b, 0, out_b, 0, 12); + System.arraycopy(data_b, 12+16, out_b, 12+16, data_b.length-12-16); + + Date date = sdf.parse("2006-01-24 21:25:03.725"); + SystemTimeUtils.storeDate(date, out_b, 12); + + for(int i=0; i<out_b.length; i++) { + assertEquals(data_b[i], out_b[i]); + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hsmf/TestBasics.java b/poi-scratchpad/src/test/java/org/apache/poi/hsmf/TestBasics.java index ce219e3e04..25b5442ac2 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hsmf/TestBasics.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hsmf/TestBasics.java @@ -74,10 +74,10 @@ public final class TestBasics { // This one has lots... assertEquals(18, outlook30.getRecipientEmailAddressList().length); assertEquals("shawn.bohn@pnl.gov; gus.calapristi@pnl.gov; Richard.Carter@pnl.gov; " + - "barb.cheney@pnl.gov; nick.cramer@pnl.gov; vern.crow@pnl.gov; Laura.Curtis@pnl.gov; " + - "julie.dunkle@pnl.gov; david.gillen@pnl.gov; michelle@pnl.gov; Jereme.Haack@pnl.gov; " + - "Michelle.Hart@pnl.gov; ranata.johnson@pnl.gov; grant.nakamura@pnl.gov; " + - "debbie.payne@pnl.gov; stuart.rose@pnl.gov; randall.scarberry@pnl.gov; Leigh.Williams@pnl.gov", + "barb.cheney@pnl.gov; nick.cramer@pnl.gov; vern.crow@pnl.gov; Laura.Curtis@pnl.gov; " + + "julie.dunkle@pnl.gov; david.gillen@pnl.gov; michelle@pnl.gov; Jereme.Haack@pnl.gov; " + + "Michelle.Hart@pnl.gov; ranata.johnson@pnl.gov; grant.nakamura@pnl.gov; " + + "debbie.payne@pnl.gov; stuart.rose@pnl.gov; randall.scarberry@pnl.gov; Leigh.Williams@pnl.gov", outlook30.getRecipientEmailAddress() ); } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hsmf/datatypes/TestChunkData.java b/poi-scratchpad/src/test/java/org/apache/poi/hsmf/datatypes/TestChunkData.java index d61ec49805..9574ac6b73 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hsmf/datatypes/TestChunkData.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hsmf/datatypes/TestChunkData.java @@ -26,14 +26,14 @@ import org.junit.jupiter.api.Test; * that will break the library. */ public final class TestChunkData { - @Test - void testChunkCreate() { - Chunk chunk; + @Test + void testChunkCreate() { + Chunk chunk; - chunk = new StringChunk(0x0200, Types.createCustom(0x001E)); - assertEquals("__substg1.0_0200001E", chunk.getEntryName()); - assertEquals(0x0200, chunk.getChunkId()); - assertEquals(0x001E, chunk.getType().getId()); + chunk = new StringChunk(0x0200, Types.createCustom(0x001E)); + assertEquals("__substg1.0_0200001E", chunk.getEntryName()); + assertEquals(0x0200, chunk.getChunkId()); + assertEquals(0x001E, chunk.getType().getId()); chunk = new StringChunk("__substg1.0_", 0x0200, Types.createCustom(0x001E)); assertEquals("__substg1.0_0200001E", chunk.getEntryName()); @@ -45,46 +45,46 @@ public final class TestChunkData { assertEquals(0x0200, chunk.getChunkId()); assertEquals(0x001E, chunk.getType().getId()); - /* test the lower and upper limits of the chunk ids */ - chunk = new StringChunk(0x0000, Types.createCustom(0x001E)); - assertEquals("__substg1.0_0000001E", chunk.getEntryName()); + /* test the lower and upper limits of the chunk ids */ + chunk = new StringChunk(0x0000, Types.createCustom(0x001E)); + assertEquals("__substg1.0_0000001E", chunk.getEntryName()); - chunk = new StringChunk(0xFFFF, Types.createCustom(0x001E)); - assertEquals("__substg1.0_FFFF001E", chunk.getEntryName()); + chunk = new StringChunk(0xFFFF, Types.createCustom(0x001E)); + assertEquals("__substg1.0_FFFF001E", chunk.getEntryName()); - chunk = new StringChunk(0xFFFF, Types.createCustom(0x001F)); - assertEquals("__substg1.0_FFFF001F", chunk.getEntryName()); - } + chunk = new StringChunk(0xFFFF, Types.createCustom(0x001F)); + assertEquals("__substg1.0_FFFF001F", chunk.getEntryName()); + } - @Test - void testTextBodyChunk() { - StringChunk chunk = new StringChunk(0x1000, Types.UNICODE_STRING); - assertEquals(chunk.getChunkId(), MAPIProperty.BODY.id); - } + @Test + void testTextBodyChunk() { + StringChunk chunk = new StringChunk(0x1000, Types.UNICODE_STRING); + assertEquals(chunk.getChunkId(), MAPIProperty.BODY.id); + } - @Test - void testDisplayToChunk() { - StringChunk chunk = new StringChunk(0x0E04, Types.UNICODE_STRING); + @Test + void testDisplayToChunk() { + StringChunk chunk = new StringChunk(0x0E04, Types.UNICODE_STRING); assertEquals(chunk.getChunkId(), MAPIProperty.DISPLAY_TO.id); - } + } - @Test - void testDisplayCCChunk() { - StringChunk chunk = new StringChunk(0x0E03, Types.UNICODE_STRING); + @Test + void testDisplayCCChunk() { + StringChunk chunk = new StringChunk(0x0E03, Types.UNICODE_STRING); assertEquals(chunk.getChunkId(), MAPIProperty.DISPLAY_CC.id); - } + } - @Test - void testDisplayBCCChunk() { - StringChunk chunk = new StringChunk(0x0E02, Types.UNICODE_STRING); + @Test + void testDisplayBCCChunk() { + StringChunk chunk = new StringChunk(0x0E02, Types.UNICODE_STRING); assertEquals(chunk.getChunkId(), MAPIProperty.DISPLAY_BCC.id); - } + } - @Test - void testSubjectChunk() { - Chunk chunk = new StringChunk(0x0037, Types.UNICODE_STRING); + @Test + void testSubjectChunk() { + Chunk chunk = new StringChunk(0x0037, Types.UNICODE_STRING); assertEquals(chunk.getChunkId(), MAPIProperty.SUBJECT.id); - } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java b/poi-scratchpad/src/test/java/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java index f2070fcdb3..528fefd548 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java @@ -252,7 +252,7 @@ public final class TestPOIFSChunkParser { @Test void testFindsAttachments() throws IOException, ChunkNotFoundException { - POIFSFileSystem with = new POIFSFileSystem(samples.getFile("attachment_test_msg.msg"), true); + POIFSFileSystem with = new POIFSFileSystem(samples.getFile("attachment_test_msg.msg"), true); POIFSFileSystem without = new POIFSFileSystem(samples.getFile("quick.msg"), true); AttachmentChunks attachment; @@ -285,7 +285,7 @@ public final class TestPOIFSChunkParser { assertFalse(without.getRoot().hasEntry("__attach_version1.0_#00000000")); assertFalse(without.getRoot().hasEntry("__attach_version1.0_#00000001")); - // One with, from the top + // One with, from the top MAPIMessage msgWith = new MAPIMessage(with); assertEquals(2, msgWith.getAttachmentFiles().length); @@ -304,7 +304,7 @@ public final class TestPOIFSChunkParser { assertEquals("Nicolas1 23456", msgWith.getDisplayFrom()); assertEquals("test pi\u00e8ce jointe 1", msgWith.getSubject()); - // One without, from the top + // One without, from the top MAPIMessage msgWithout = new MAPIMessage(without); // No attachments diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestHWPFPictures.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestHWPFPictures.java index 9a9b942a25..0b262ecfee 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestHWPFPictures.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestHWPFPictures.java @@ -39,85 +39,85 @@ import org.junit.jupiter.api.Test; * Test picture support in HWPF */ public final class TestHWPFPictures { - @BeforeAll + @BeforeAll static void setUp() { - // we use ImageIO in one of the tests here so we should ensure that the temporary directory is created correctly - File tempDir = new File(System.getProperty("java.io.tmpdir")); - assertTrue( tempDir.exists() || tempDir.mkdirs(), "Could not create temporary directory " + tempDir.getAbsolutePath() + ": " + tempDir.exists() + "/" + tempDir.isDirectory() ); - } - - /** - * Test that we have the right numbers of images in each file - */ - @Test - void testImageCount() { - HWPFDocument docA = HWPFTestDataSamples.openSampleFile("testPictures.doc"); - HWPFDocument docB = HWPFTestDataSamples.openSampleFile("two_images.doc"); - - assertNotNull(docA.getPicturesTable()); - assertNotNull(docB.getPicturesTable()); - - PicturesTable picA = docA.getPicturesTable(); - PicturesTable picB = docB.getPicturesTable(); - - List<Picture> picturesA = picA.getAllPictures(); - List<Picture> picturesB = picB.getAllPictures(); - - assertEquals(7, picturesA.size()); - assertEquals(2, picturesB.size()); - } - - /** - * Test that we have the right images in at least one file - */ - @Test - void testImageData() { - HWPFDocument docB = HWPFTestDataSamples.openSampleFile("two_images.doc"); - PicturesTable picB = docB.getPicturesTable(); - List<Picture> picturesB = picB.getAllPictures(); - - assertEquals(2, picturesB.size()); - - Picture pic1 = picturesB.get(0); - Picture pic2 = picturesB.get(1); - - assertNotNull(pic1); - assertNotNull(pic2); - - // Check the same - byte[] pic1B = readFile("simple_image.jpg"); - byte[] pic2B = readFile("simple_image.png"); - - assertArrayEquals(pic1B, pic1.getContent()); - assertArrayEquals(pic2B, pic2.getContent()); - } - - /** - * Test that compressed image data is correctly returned. - */ - @Test - void testCompressedImageData() { - HWPFDocument docC = HWPFTestDataSamples.openSampleFile("vector_image.doc"); - PicturesTable picC = docC.getPicturesTable(); - List<Picture> picturesC = picC.getAllPictures(); - - assertEquals(1, picturesC.size()); - - Picture pic = picturesC.get(0); - assertNotNull(pic); - - // Check the same - byte[] picBytes = readFile("vector_image.emf"); - assertArrayEquals(picBytes, pic.getContent()); - } - - @Test - void testMacImages() throws Exception { + // we use ImageIO in one of the tests here so we should ensure that the temporary directory is created correctly + File tempDir = new File(System.getProperty("java.io.tmpdir")); + assertTrue( tempDir.exists() || tempDir.mkdirs(), "Could not create temporary directory " + tempDir.getAbsolutePath() + ": " + tempDir.exists() + "/" + tempDir.isDirectory() ); + } + + /** + * Test that we have the right numbers of images in each file + */ + @Test + void testImageCount() { + HWPFDocument docA = HWPFTestDataSamples.openSampleFile("testPictures.doc"); + HWPFDocument docB = HWPFTestDataSamples.openSampleFile("two_images.doc"); + + assertNotNull(docA.getPicturesTable()); + assertNotNull(docB.getPicturesTable()); + + PicturesTable picA = docA.getPicturesTable(); + PicturesTable picB = docB.getPicturesTable(); + + List<Picture> picturesA = picA.getAllPictures(); + List<Picture> picturesB = picB.getAllPictures(); + + assertEquals(7, picturesA.size()); + assertEquals(2, picturesB.size()); + } + + /** + * Test that we have the right images in at least one file + */ + @Test + void testImageData() { + HWPFDocument docB = HWPFTestDataSamples.openSampleFile("two_images.doc"); + PicturesTable picB = docB.getPicturesTable(); + List<Picture> picturesB = picB.getAllPictures(); + + assertEquals(2, picturesB.size()); + + Picture pic1 = picturesB.get(0); + Picture pic2 = picturesB.get(1); + + assertNotNull(pic1); + assertNotNull(pic2); + + // Check the same + byte[] pic1B = readFile("simple_image.jpg"); + byte[] pic2B = readFile("simple_image.png"); + + assertArrayEquals(pic1B, pic1.getContent()); + assertArrayEquals(pic2B, pic2.getContent()); + } + + /** + * Test that compressed image data is correctly returned. + */ + @Test + void testCompressedImageData() { + HWPFDocument docC = HWPFTestDataSamples.openSampleFile("vector_image.doc"); + PicturesTable picC = docC.getPicturesTable(); + List<Picture> picturesC = picC.getAllPictures(); + + assertEquals(1, picturesC.size()); + + Picture pic = picturesC.get(0); + assertNotNull(pic); + + // Check the same + byte[] picBytes = readFile("vector_image.emf"); + assertArrayEquals(picBytes, pic.getContent()); + } + + @Test + void testMacImages() throws Exception { HWPFDocument docC = HWPFTestDataSamples.openSampleFile("53446.doc"); - PicturesTable picturesTable = docC.getPicturesTable(); - List<Picture> pictures = picturesTable.getAllPictures(); + PicturesTable picturesTable = docC.getPicturesTable(); + List<Picture> pictures = picturesTable.getAllPictures(); - assertEquals(4, pictures.size()); + assertEquals(4, pictures.size()); int[][] expectedSizes = { { 185, 42 }, // PNG @@ -134,29 +134,29 @@ public final class TestHWPFPictures { assertEquals(dimensions[0], image.getWidth()); assertEquals(dimensions[1], image.getHeight()); } - } + } - /** - * Pending the missing files being uploaded to - * bug #44937 - */ - @Test - void testEscherDrawing() { - HWPFDocument docD = HWPFTestDataSamples.openSampleFile("GaiaTest.doc"); - List<Picture> allPictures = docD.getPicturesTable().getAllPictures(); + /** + * Pending the missing files being uploaded to + * bug #44937 + */ + @Test + void testEscherDrawing() { + HWPFDocument docD = HWPFTestDataSamples.openSampleFile("GaiaTest.doc"); + List<Picture> allPictures = docD.getPicturesTable().getAllPictures(); - assertEquals(1, allPictures.size()); + assertEquals(1, allPictures.size()); - Picture pic = allPictures.get(0); - assertNotNull(pic); - byte[] picD = readFile("GaiaTestImg.png"); + Picture pic = allPictures.get(0); + assertNotNull(pic); + byte[] picD = readFile("GaiaTestImg.png"); - assertEquals(picD.length, pic.getContent().length); + assertEquals(picD.length, pic.getContent().length); - assertArrayEquals(picD, pic.getContent()); - } + assertArrayEquals(picD, pic.getContent()); + } - private static byte[] readFile(String file) { - return POIDataSamples.getDocumentInstance().readFile(file); - } + private static byte[] readFile(String file) { + return POIDataSamples.getDocumentInstance().readFile(file); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestHWPFRangeParts.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestHWPFRangeParts.java index d7d7ed6249..8a41b3adae 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestHWPFRangeParts.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/TestHWPFRangeParts.java @@ -27,78 +27,78 @@ import org.junit.jupiter.api.Test; * Test that we pull out the right bits of a file into the different ranges */ public final class TestHWPFRangeParts { - private static final char page_break = (char)12; - private static final String headerDef = - "\u0003\r\r" + - "\u0004\r\r" + - "\u0003\r\r" + - "\u0004\r\r" - ; - private static final String footerDef = "\r"; - private static final String endHeaderFooter = "\r\r"; - - - private static final String a_page_1 = - "This is a sample word document. It has two pages. It has a three column heading, and a three column footer\r" + - "\r" + - "HEADING TEXT\r" + - "\r" + - "More on page one\r" + - "\r\r" + - "End of page 1\r" - ; - private static final String a_page_2 = - "This is page two. It also has a three column heading, and a three column footer.\r" - ; - - private static final String a_header = - "First header column!\tMid header Right header!\r" - ; - private static final String a_footer = - "Footer Left\tFooter Middle Footer Right\r" - ; - - - private static final String u_page_1 = - "This is a fairly simple word document, over two pages, with headers and footers.\r" + - "The trick with this one is that it contains some Unicode based strings in it.\r" + - "Firstly, some currency symbols:\r" + - "\tGBP - \u00a3\r" + - "\tEUR - \u20ac\r" + - "Now, we\u2019ll have some French text, in bold and big:\r" + - "\tMoli\u00e8re\r" + - "And some normal French text:\r" + - "\tL'Avare ou l'\u00c9cole du mensonge\r" + - "That\u2019s it for page one\r" - ; - private static final String u_page_2 = - "This is page two. Les Pr\u00e9cieuses ridicules. The end.\r" - ; - - private static final String u_header = - "\r\r" + - "This is a simple header, with a \u20ac euro symbol in it.\r" - ; - private static final String u_footer = - "\r\r\r" + - "The footer, with Moli\u00e8re, has Unicode in it.\r" + - "\r\r\r\r" - ; - - /** - * A document made up only of basic ASCII text - */ - private HWPFDocument docAscii; - /** - * A document with some unicode in it too - */ - private HWPFDocument docUnicode; - - @BeforeEach + private static final char page_break = (char)12; + private static final String headerDef = + "\u0003\r\r" + + "\u0004\r\r" + + "\u0003\r\r" + + "\u0004\r\r" + ; + private static final String footerDef = "\r"; + private static final String endHeaderFooter = "\r\r"; + + + private static final String a_page_1 = + "This is a sample word document. It has two pages. It has a three column heading, and a three column footer\r" + + "\r" + + "HEADING TEXT\r" + + "\r" + + "More on page one\r" + + "\r\r" + + "End of page 1\r" + ; + private static final String a_page_2 = + "This is page two. It also has a three column heading, and a three column footer.\r" + ; + + private static final String a_header = + "First header column!\tMid header Right header!\r" + ; + private static final String a_footer = + "Footer Left\tFooter Middle Footer Right\r" + ; + + + private static final String u_page_1 = + "This is a fairly simple word document, over two pages, with headers and footers.\r" + + "The trick with this one is that it contains some Unicode based strings in it.\r" + + "Firstly, some currency symbols:\r" + + "\tGBP - \u00a3\r" + + "\tEUR - \u20ac\r" + + "Now, we\u2019ll have some French text, in bold and big:\r" + + "\tMoli\u00e8re\r" + + "And some normal French text:\r" + + "\tL'Avare ou l'\u00c9cole du mensonge\r" + + "That\u2019s it for page one\r" + ; + private static final String u_page_2 = + "This is page two. Les Pr\u00e9cieuses ridicules. The end.\r" + ; + + private static final String u_header = + "\r\r" + + "This is a simple header, with a \u20ac euro symbol in it.\r" + ; + private static final String u_footer = + "\r\r\r" + + "The footer, with Moli\u00e8re, has Unicode in it.\r" + + "\r\r\r\r" + ; + + /** + * A document made up only of basic ASCII text + */ + private HWPFDocument docAscii; + /** + * A document with some unicode in it too + */ + private HWPFDocument docUnicode; + + @BeforeEach void setUp() { - docUnicode = HWPFTestDataSamples.openSampleFile("HeaderFooterUnicode.doc"); - docAscii = HWPFTestDataSamples.openSampleFile("ThreeColHeadFoot.doc"); - } + docUnicode = HWPFTestDataSamples.openSampleFile("HeaderFooterUnicode.doc"); + docAscii = HWPFTestDataSamples.openSampleFile("ThreeColHeadFoot.doc"); + } /** * Note - this test runs several times, to ensure that things @@ -106,43 +106,43 @@ public final class TestHWPFRangeParts { * TODO - Make this work with 3+ runs */ @Test - void testContents() { + void testContents() { HWPFDocument doc = docAscii; for(int run=0; run<3; run++) { - Range r; - - // Now check the real ranges - r = doc.getRange(); - assertEquals( - a_page_1 + - page_break + "\r" + - a_page_2, - r.text() - ); - - r = doc.getHeaderStoryRange(); - assertEquals( - headerDef + - a_header + - footerDef + - a_footer + - endHeaderFooter, - r.text() - ); - - r = doc.getOverallRange(); - assertEquals( - a_page_1 + - page_break + "\r" + - a_page_2 + - headerDef + - a_header + - footerDef + - a_footer + - endHeaderFooter + - "\r", - r.text() - ); + Range r; + + // Now check the real ranges + r = doc.getRange(); + assertEquals( + a_page_1 + + page_break + "\r" + + a_page_2, + r.text() + ); + + r = doc.getHeaderStoryRange(); + assertEquals( + headerDef + + a_header + + footerDef + + a_footer + + endHeaderFooter, + r.text() + ); + + r = doc.getOverallRange(); + assertEquals( + a_page_1 + + page_break + "\r" + + a_page_2 + + headerDef + + a_header + + footerDef + + a_footer + + endHeaderFooter + + "\r", + r.text() + ); // Write out and read back in again, ready for // the next run of the test @@ -150,43 +150,43 @@ public final class TestHWPFRangeParts { if(run < 1) doc = HWPFTestDataSamples.writeOutAndReadBack(doc); } - } - - @Test - void testContentsUnicode() { - Range r; - - // Now check the real ranges - r = docUnicode.getRange(); - assertEquals( - u_page_1 + - page_break + "\r" + - u_page_2, - r.text() - ); - - r = docUnicode.getHeaderStoryRange(); - assertEquals( - headerDef + - u_header + - footerDef + - u_footer + - endHeaderFooter, - r.text() - ); - - r = docUnicode.getOverallRange(); - assertEquals( - u_page_1 + - page_break + "\r" + - u_page_2 + - headerDef + - u_header + - footerDef + - u_footer + - endHeaderFooter + - "\r", - r.text() - ); - } + } + + @Test + void testContentsUnicode() { + Range r; + + // Now check the real ranges + r = docUnicode.getRange(); + assertEquals( + u_page_1 + + page_break + "\r" + + u_page_2, + r.text() + ); + + r = docUnicode.getHeaderStoryRange(); + assertEquals( + headerDef + + u_header + + footerDef + + u_footer + + endHeaderFooter, + r.text() + ); + + r = docUnicode.getOverallRange(); + assertEquals( + u_page_1 + + page_break + "\r" + + u_page_2 + + headerDef + + u_header + + footerDef + + u_footer + + endHeaderFooter + + "\r", + r.text() + ); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestDifferentRoutes.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestDifferentRoutes.java index 331085ae4a..f29ee52e60 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestDifferentRoutes.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestDifferentRoutes.java @@ -35,57 +35,57 @@ import org.junit.jupiter.api.Test; * Test the different routes to extracting text */ public final class TestDifferentRoutes { - private static final String[] p_text = new String[] { - "This is a simple word document\r", - "\r", - "It has a number of paragraphs in it\r", - "\r", - "Some of them even feature bold, italic and underlined text\r", - "\r", - "\r", - "This bit is in a different font and size\r", - "\r", - "\r", - "This bit features some red text.\r", - "\r", - "\r", - "It is otherwise very very boring.\r" - }; + private static final String[] p_text = new String[] { + "This is a simple word document\r", + "\r", + "It has a number of paragraphs in it\r", + "\r", + "Some of them even feature bold, italic and underlined text\r", + "\r", + "\r", + "This bit is in a different font and size\r", + "\r", + "\r", + "This bit features some red text.\r", + "\r", + "\r", + "It is otherwise very very boring.\r" + }; - private HWPFDocument doc; + private HWPFDocument doc; - @BeforeEach - void setUp() { - doc = HWPFTestDataSamples.openSampleFile("test2.doc"); - } + @BeforeEach + void setUp() { + doc = HWPFTestDataSamples.openSampleFile("test2.doc"); + } - @AfterEach - void tearDown() throws IOException { - doc.close(); - } + @AfterEach + void tearDown() throws IOException { + doc.close(); + } - /** - * Test model based extraction - */ - @Test - void testExtractFromModel() { - Range r = doc.getRange(); + /** + * Test model based extraction + */ + @Test + void testExtractFromModel() { + Range r = doc.getRange(); - String[] text = new String[r.numParagraphs()]; - for (int i = 0; i < r.numParagraphs(); i++) { - Paragraph p = r.getParagraph(i); - text[i] = p.text(); - } + String[] text = new String[r.numParagraphs()]; + for (int i = 0; i < r.numParagraphs(); i++) { + Paragraph p = r.getParagraph(i); + text[i] = p.text(); + } - assertArrayEquals(p_text, text); - } + assertArrayEquals(p_text, text); + } - /** - * Test textPieces based extraction - */ - @Test - void testExtractFromTextPieces() throws Exception { - String expected = StringUtil.join(p_text, ""); - assertEquals(expected, doc.getDocumentText()); - } + /** + * Test textPieces based extraction + */ + @Test + void testExtractFromTextPieces() throws Exception { + String expected = StringUtil.join(p_text, ""); + assertEquals(expected, doc.getDocumentText()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractor.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractor.java index f250b5daa4..2e67e0ff03 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractor.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractor.java @@ -60,54 +60,54 @@ public final class TestWordExtractor { assertContains(endnote, needle); } - private final String[] p_text1 = new String[] { - "This is a simple word document\r\n", - "\r\n", - "It has a number of paragraphs in it\r\n", - "\r\n", - "Some of them even feature bold, italic and underlined text\r\n", - "\r\n", - "\r\n", - "This bit is in a different font and size\r\n", - "\r\n", - "\r\n", - "This bit features some red text.\r\n", - "\r\n", - "\r\n", - "It is otherwise very very boring.\r\n" - }; + private final String[] p_text1 = new String[] { + "This is a simple word document\r\n", + "\r\n", + "It has a number of paragraphs in it\r\n", + "\r\n", + "Some of them even feature bold, italic and underlined text\r\n", + "\r\n", + "\r\n", + "This bit is in a different font and size\r\n", + "\r\n", + "\r\n", + "This bit features some red text.\r\n", + "\r\n", + "\r\n", + "It is otherwise very very boring.\r\n" + }; // Build splat'd out text version - private final String p_text1_block = StringUtil.join(p_text1, ""); + private final String p_text1_block = StringUtil.join(p_text1, ""); - /** - * Test paragraph based extraction - */ - @Test - void testExtractFromParagraphs() throws IOException { + /** + * Test paragraph based extraction + */ + @Test + void testExtractFromParagraphs() throws IOException { WordExtractor extractor = openExtractor("test2.doc"); - String[] text = extractor.getParagraphText(); + String[] text = extractor.getParagraphText(); - assertEquals(p_text1.length, text.length); - for (int i = 0; i < p_text1.length; i++) { - assertEquals(p_text1[i], text[i]); - } + assertEquals(p_text1.length, text.length); + for (int i = 0; i < p_text1.length; i++) { + assertEquals(p_text1[i], text[i]); + } extractor.close(); - // Lots of paragraphs with only a few lines in them + // Lots of paragraphs with only a few lines in them WordExtractor extractor2 = openExtractor("test.doc"); - assertEquals(24, extractor2.getParagraphText().length); - assertEquals("as d\r\n", extractor2.getParagraphText()[16]); - assertEquals("as d\r\n", extractor2.getParagraphText()[17]); - assertEquals("as d\r\n", extractor2.getParagraphText()[18]); - extractor2.close(); - } - - /** - * Test the paragraph -> flat extraction - */ + assertEquals(24, extractor2.getParagraphText().length); + assertEquals("as d\r\n", extractor2.getParagraphText()[16]); + assertEquals("as d\r\n", extractor2.getParagraphText()[17]); + assertEquals("as d\r\n", extractor2.getParagraphText()[18]); + extractor2.close(); + } + + /** + * Test the paragraph -> flat extraction + */ @Test - void testGetText() throws IOException { + void testGetText() throws IOException { WordExtractor extractor = openExtractor("test2.doc"); assertEqualsTrim(p_text1_block, extractor.getText()); @@ -118,148 +118,148 @@ public final class TestWordExtractor { // assertEquals( // extractor2.getTextFromPieces().replaceAll("[\\r\\n]", ""), // extractor2.getText().replaceAll("[\\r\\n]", "")); - extractor.close(); + extractor.close(); } - /** - * Test textPieces based extraction - */ + /** + * Test textPieces based extraction + */ @Test - void testExtractFromTextPieces() throws IOException { + void testExtractFromTextPieces() throws IOException { WordExtractor extractor = openExtractor("test2.doc"); - String text = extractor.getTextFromPieces(); - assertEquals(p_text1_block, text); - extractor.close(); - } + String text = extractor.getTextFromPieces(); + assertEquals(p_text1_block, text); + extractor.close(); + } - /** - * Test that we can get data from two different embedded word documents - */ + /** + * Test that we can get data from two different embedded word documents + */ @Test - void testExtractFromEmbeded() throws IOException { - InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("excel_with_embeded.xls"); - POIFSFileSystem fs = new POIFSFileSystem(is); - is.close(); + void testExtractFromEmbeded() throws IOException { + InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("excel_with_embeded.xls"); + POIFSFileSystem fs = new POIFSFileSystem(is); + is.close(); - DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B7"); - DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B2"); + DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B7"); + DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B2"); - // Should have WordDocument and 1Table - assertNotNull(dirA.getEntry("1Table")); - assertNotNull(dirA.getEntry("WordDocument")); + // Should have WordDocument and 1Table + assertNotNull(dirA.getEntry("1Table")); + assertNotNull(dirA.getEntry("WordDocument")); - assertNotNull(dirB.getEntry("1Table")); - assertNotNull(dirB.getEntry("WordDocument")); + assertNotNull(dirB.getEntry("1Table")); + assertNotNull(dirB.getEntry("WordDocument")); - // Check each in turn + // Check each in turn HWPFDocument docA = new HWPFDocument(dirA); - WordExtractor extractorA = new WordExtractor(docA); + WordExtractor extractorA = new WordExtractor(docA); - assertNotNull(extractorA.getText()); - assertTrue(extractorA.getText().length() > 20); - assertEqualsTrim("I am a sample document\r\nNot much on me\r\nI am document 1\r\n", extractorA.getText()); - assertEquals("Sample Doc 1", extractorA.getSummaryInformation().getTitle()); - assertEquals("Sample Test", extractorA.getSummaryInformation().getSubject()); + assertNotNull(extractorA.getText()); + assertTrue(extractorA.getText().length() > 20); + assertEqualsTrim("I am a sample document\r\nNot much on me\r\nI am document 1\r\n", extractorA.getText()); + assertEquals("Sample Doc 1", extractorA.getSummaryInformation().getTitle()); + assertEquals("Sample Test", extractorA.getSummaryInformation().getSubject()); - HWPFDocument docB = new HWPFDocument(dirB); - WordExtractor extractorB = new WordExtractor(docB); + HWPFDocument docB = new HWPFDocument(dirB); + WordExtractor extractorB = new WordExtractor(docB); - assertNotNull(extractorB.getText()); - assertTrue(extractorB.getText().length() > 20); - assertEqualsTrim("I am another sample document\r\nNot much on me\r\nI am document 2\r\n", extractorB.getText()); - assertEquals("Sample Doc 2", extractorB.getSummaryInformation().getTitle()); - assertEquals("Another Sample Test", extractorB.getSummaryInformation().getSubject()); + assertNotNull(extractorB.getText()); + assertTrue(extractorB.getText().length() > 20); + assertEqualsTrim("I am another sample document\r\nNot much on me\r\nI am document 2\r\n", extractorB.getText()); + assertEquals("Sample Doc 2", extractorB.getSummaryInformation().getTitle()); + assertEquals("Another Sample Test", extractorB.getSummaryInformation().getSubject()); - extractorA.close(); - docA.close(); + extractorA.close(); + docA.close(); - extractorB.close(); - docB.close(); + extractorB.close(); + docB.close(); - fs.close(); - } + fs.close(); + } @Test - void testWithHeader() throws IOException { - // Non-unicode - HWPFDocument doc1 = HWPFTestDataSamples.openSampleFile("ThreeColHeadFoot.doc"); - WordExtractor extractor1 = new WordExtractor(doc1); + void testWithHeader() throws IOException { + // Non-unicode + HWPFDocument doc1 = HWPFTestDataSamples.openSampleFile("ThreeColHeadFoot.doc"); + WordExtractor extractor1 = new WordExtractor(doc1); //noinspection deprecation assertEquals("First header column!\tMid header Right header!\n", extractor1.getHeaderText()); - assertContains(extractor1.getText(), "First header column!"); - extractor1.close(); - doc1.close(); + assertContains(extractor1.getText(), "First header column!"); + extractor1.close(); + doc1.close(); - // Unicode - HWPFDocument doc2 = HWPFTestDataSamples.openSampleFile("HeaderFooterUnicode.doc"); - WordExtractor extractor2 = new WordExtractor(doc2); + // Unicode + HWPFDocument doc2 = HWPFTestDataSamples.openSampleFile("HeaderFooterUnicode.doc"); + WordExtractor extractor2 = new WordExtractor(doc2); //noinspection deprecation assertEquals("This is a simple header, with a \u20ac euro symbol in it.\n\n", extractor2.getHeaderText()); - assertContains(extractor2.getText(), "This is a simple header"); - extractor2.close(); - doc2.close(); - } + assertContains(extractor2.getText(), "This is a simple header"); + extractor2.close(); + doc2.close(); + } @Test - void testWithFooter() throws IOException { - // Non-unicode - HWPFDocument doc1 = HWPFTestDataSamples.openSampleFile("ThreeColHeadFoot.doc"); - WordExtractor extractor1 = new WordExtractor(doc1); + void testWithFooter() throws IOException { + // Non-unicode + HWPFDocument doc1 = HWPFTestDataSamples.openSampleFile("ThreeColHeadFoot.doc"); + WordExtractor extractor1 = new WordExtractor(doc1); //noinspection deprecation assertEquals("Footer Left\tFooter Middle Footer Right\n", extractor1.getFooterText()); - assertContains(extractor1.getText(), "Footer Left"); + assertContains(extractor1.getText(), "Footer Left"); extractor1.close(); doc1.close(); - // Unicode - HWPFDocument doc2 = HWPFTestDataSamples.openSampleFile("HeaderFooterUnicode.doc"); - WordExtractor extractor2 = new WordExtractor(doc2); + // Unicode + HWPFDocument doc2 = HWPFTestDataSamples.openSampleFile("HeaderFooterUnicode.doc"); + WordExtractor extractor2 = new WordExtractor(doc2); //noinspection deprecation assertEquals("The footer, with Moli\u00e8re, has Unicode in it.\n", extractor2.getFooterText()); - assertContains(extractor2.getText(), "The footer, with"); + assertContains(extractor2.getText(), "The footer, with"); extractor2.close(); doc2.close(); - } + } @Test - void testFootnote() throws IOException { - HWPFDocument doc = HWPFTestDataSamples.openSampleFile("footnote.doc"); - WordExtractor extractor = new WordExtractor(doc); - - assertExtractedContains(extractor.getFootnoteText(), "TestFootnote"); - assertEquals(0x00, doc.getRange().getSection(0).getFootnoteNumberingFormat()); // msonfcArabic - assertEquals(0x00, doc.getRange().getSection(0).getFootnoteRestartQualifier()); // rncCont - assertEquals(0, doc.getRange().getSection(0).getFootnoteNumberingOffset()); - assertEquals(1, doc.getFootnotes().getNotesCount()); - extractor.close(); - doc.close(); - } + void testFootnote() throws IOException { + HWPFDocument doc = HWPFTestDataSamples.openSampleFile("footnote.doc"); + WordExtractor extractor = new WordExtractor(doc); + + assertExtractedContains(extractor.getFootnoteText(), "TestFootnote"); + assertEquals(0x00, doc.getRange().getSection(0).getFootnoteNumberingFormat()); // msonfcArabic + assertEquals(0x00, doc.getRange().getSection(0).getFootnoteRestartQualifier()); // rncCont + assertEquals(0, doc.getRange().getSection(0).getFootnoteNumberingOffset()); + assertEquals(1, doc.getFootnotes().getNotesCount()); + extractor.close(); + doc.close(); + } @Test - void testEndnote() throws IOException { - HWPFDocument doc = HWPFTestDataSamples.openSampleFile("footnote.doc"); - WordExtractor extractor = new WordExtractor(doc); - - assertExtractedContains(extractor.getEndnoteText(), "TestEndnote"); - assertEquals(0x02, doc.getRange().getSection(0).getEndnoteNumberingFormat()); // msonfcLCRoman - assertEquals(0x00, doc.getRange().getSection(0).getEndnoteRestartQualifier()); // rncCont - assertEquals(0, doc.getRange().getSection(0).getEndnoteNumberingOffset()); - assertEquals(1, doc.getEndnotes().getNotesCount()); - extractor.close(); - doc.close(); - } + void testEndnote() throws IOException { + HWPFDocument doc = HWPFTestDataSamples.openSampleFile("footnote.doc"); + WordExtractor extractor = new WordExtractor(doc); + + assertExtractedContains(extractor.getEndnoteText(), "TestEndnote"); + assertEquals(0x02, doc.getRange().getSection(0).getEndnoteNumberingFormat()); // msonfcLCRoman + assertEquals(0x00, doc.getRange().getSection(0).getEndnoteRestartQualifier()); // rncCont + assertEquals(0, doc.getRange().getSection(0).getEndnoteNumberingOffset()); + assertEquals(1, doc.getEndnotes().getNotesCount()); + extractor.close(); + doc.close(); + } @Test - void testComments() throws IOException { - WordExtractor extractor = openExtractor("footnote.doc"); - assertExtractedContains(extractor.getCommentsText(), "TestComment"); - extractor.close(); - } + void testComments() throws IOException { + WordExtractor extractor = openExtractor("footnote.doc"); + assertExtractedContains(extractor.getCommentsText(), "TestComment"); + extractor.close(); + } @Test void testWord95_WordExtractor() { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractorBugs.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractorBugs.java index 5575a09291..db46f947f0 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractorBugs.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractorBugs.java @@ -56,5 +56,5 @@ public final class TestWordExtractorBugs { assertNotNull(extractor.getParagraphText()); } } - } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/model/TestSectionTable.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/model/TestSectionTable.java index 63ab183e75..d489d7ad6c 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/model/TestSectionTable.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/model/TestSectionTable.java @@ -55,8 +55,8 @@ public final class TestSectionTable { byte[] newMainStream = mainOut.toByteArray(); SectionTable newSectionTable = new SectionTable( - newMainStream, newTableStream, 0, - newTableStream.length, 0, tpt, fib.getSubdocumentTextStreamLength( SubdocumentType.MAIN )); + newMainStream, newTableStream, 0, + newTableStream.length, 0, tpt, fib.getSubdocumentTextStreamLength( SubdocumentType.MAIN )); List<SEPX> oldSections = sectionTable.getSections(); List<SEPX> newSections = newSectionTable.getSections(); @@ -79,8 +79,8 @@ public final class TestSectionTable { int size = oldSections.size(); for (int x = 0; x < size; x++) { - SEPX oldNode = oldSections.get(x); - SEPX newNode = newSections.get(x); + SEPX oldNode = oldSections.get(x); + SEPX newNode = newSections.get(x); assertEquals(oldNode, newNode); } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestBug46610.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestBug46610.java index a886141f2f..30f4fc5318 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestBug46610.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestBug46610.java @@ -26,39 +26,39 @@ import org.junit.jupiter.api.Test; public final class TestBug46610 { - @Test - void testUtf() throws Exception { - String text = runExtract("Bug46610_1.doc"); - assertNotNull(text); - } + @Test + void testUtf() throws Exception { + String text = runExtract("Bug46610_1.doc"); + assertNotNull(text); + } - @Test - void testUtf2() throws Exception { - String text = runExtract("Bug46610_2.doc"); - assertNotNull(text); - } + @Test + void testUtf2() throws Exception { + String text = runExtract("Bug46610_2.doc"); + assertNotNull(text); + } - @Test - void testExtraction() throws Exception { - String text = runExtract("Bug46610_3.doc"); - assertContains(text, "\u0421\u0412\u041e\u042e"); - } + @Test + void testExtraction() throws Exception { + String text = runExtract("Bug46610_3.doc"); + assertContains(text, "\u0421\u0412\u041e\u042e"); + } - private static String runExtract(String sampleName) throws Exception { - HWPFDocument doc = HWPFTestDataSamples.openSampleFile(sampleName); - StringBuilder out = new StringBuilder(); + private static String runExtract(String sampleName) throws Exception { + HWPFDocument doc = HWPFTestDataSamples.openSampleFile(sampleName); + StringBuilder out = new StringBuilder(); - Range globalRange = doc.getRange(); - for (int i = 0; i < globalRange.numParagraphs(); i++) { - Paragraph p = globalRange.getParagraph(i); - out.append(p.text()); - out.append("\n"); - for (int j = 0; j < p.numCharacterRuns(); j++) { - CharacterRun characterRun = p.getCharacterRun(j); - characterRun.text(); - } - doc.close(); - } - return out.toString(); - } + Range globalRange = doc.getRange(); + for (int i = 0; i < globalRange.numParagraphs(); i++) { + Paragraph p = globalRange.getParagraph(i); + out.append(p.text()); + out.append("\n"); + for (int j = 0; j < p.numCharacterRuns(); j++) { + CharacterRun characterRun = p.getCharacterRun(j); + characterRun.text(); + } + doc.close(); + } + return out.toString(); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestBug47563.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestBug47563.java index f0e17acf76..9b53b5f78d 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestBug47563.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestBug47563.java @@ -36,62 +36,62 @@ import org.junit.jupiter.params.provider.MethodSource; public class TestBug47563 { - public static Stream<Arguments> data() { - List<Arguments> data = new ArrayList<>(); - - data.add(Arguments.of( 1, 5 )); - data.add(Arguments.of( 1, 6 )); - data.add(Arguments.of( 5, 1 )); - data.add(Arguments.of( 6, 1 )); - data.add(Arguments.of( 2, 2 )); - data.add(Arguments.of( 3, 2 )); - data.add(Arguments.of( 2, 3 )); - data.add(Arguments.of( 3, 3 )); - - return data.stream(); - } - - @ParameterizedTest - @MethodSource("data") - void test(int rows, int columns) throws Exception { - // POI apparently can't create a document from scratch, - // so we need an existing empty dummy document - try (HWPFDocument doc = HWPFTestDataSamples.openSampleFile("empty.doc")) { - Range range = doc.getRange(); - range.sanityCheck(); - - Table table = range.insertTableBefore((short) columns, rows); - table.sanityCheck(); - - for (int rowIdx = 0; rowIdx < table.numRows(); rowIdx++) { - TableRow row = table.getRow(rowIdx); - row.sanityCheck(); - - for (int colIdx = 0; colIdx < row.numCells(); colIdx++) { - TableCell cell = row.getCell(colIdx); - cell.sanityCheck(); - - Paragraph par = cell.getParagraph(0); - par.sanityCheck(); - - par.insertBefore("" + (rowIdx * row.numCells() + colIdx)); - par.sanityCheck(); - - row.sanityCheck(); - table.sanityCheck(); - range.sanityCheck(); - } - } - - String text = range.text(); - String textBytes = HexDump.toHex(text.getBytes(StandardCharsets.UTF_8)); - int mustBeAfter = 0; - for (int i = 0; i < rows * columns; i++) { - int next = text.indexOf(Integer.toString(i), mustBeAfter); - assertTrue( next != -1, "Test with " + rows + "/" + columns + ": Should find " + i + - " but did not find it (" + next + ") with " + mustBeAfter + " in " + textBytes + "\n" + next); - mustBeAfter = next; - } - } - } + public static Stream<Arguments> data() { + List<Arguments> data = new ArrayList<>(); + + data.add(Arguments.of( 1, 5 )); + data.add(Arguments.of( 1, 6 )); + data.add(Arguments.of( 5, 1 )); + data.add(Arguments.of( 6, 1 )); + data.add(Arguments.of( 2, 2 )); + data.add(Arguments.of( 3, 2 )); + data.add(Arguments.of( 2, 3 )); + data.add(Arguments.of( 3, 3 )); + + return data.stream(); + } + + @ParameterizedTest + @MethodSource("data") + void test(int rows, int columns) throws Exception { + // POI apparently can't create a document from scratch, + // so we need an existing empty dummy document + try (HWPFDocument doc = HWPFTestDataSamples.openSampleFile("empty.doc")) { + Range range = doc.getRange(); + range.sanityCheck(); + + Table table = range.insertTableBefore((short) columns, rows); + table.sanityCheck(); + + for (int rowIdx = 0; rowIdx < table.numRows(); rowIdx++) { + TableRow row = table.getRow(rowIdx); + row.sanityCheck(); + + for (int colIdx = 0; colIdx < row.numCells(); colIdx++) { + TableCell cell = row.getCell(colIdx); + cell.sanityCheck(); + + Paragraph par = cell.getParagraph(0); + par.sanityCheck(); + + par.insertBefore("" + (rowIdx * row.numCells() + colIdx)); + par.sanityCheck(); + + row.sanityCheck(); + table.sanityCheck(); + range.sanityCheck(); + } + } + + String text = range.text(); + String textBytes = HexDump.toHex(text.getBytes(StandardCharsets.UTF_8)); + int mustBeAfter = 0; + for (int i = 0; i < rows * columns; i++) { + int next = text.indexOf(Integer.toString(i), mustBeAfter); + assertTrue( next != -1, "Test with " + rows + "/" + columns + ": Should find " + i + + " but did not find it (" + next + ") with " + mustBeAfter + " in " + textBytes + "\n" + next); + mustBeAfter = next; + } + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestHeaderStories.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestHeaderStories.java index 72f0c86df0..07cb7da2d9 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestHeaderStories.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestHeaderStories.java @@ -31,173 +31,173 @@ import org.junit.jupiter.api.Test; */ @SuppressWarnings("deprecation") public final class TestHeaderStories { - private HWPFDocument none; - private HWPFDocument header; - private HWPFDocument footer; - private HWPFDocument headerFooter; - private HWPFDocument oddEven; - private HWPFDocument diffFirst; - private HWPFDocument unicode; - private HWPFDocument withFields; - - @BeforeEach + private HWPFDocument none; + private HWPFDocument header; + private HWPFDocument footer; + private HWPFDocument headerFooter; + private HWPFDocument oddEven; + private HWPFDocument diffFirst; + private HWPFDocument unicode; + private HWPFDocument withFields; + + @BeforeEach void setUp() { - none = openSampleFile("NoHeadFoot.doc"); - header = openSampleFile("ThreeColHead.doc"); - footer = openSampleFile("ThreeColFoot.doc"); - headerFooter = openSampleFile("SimpleHeadThreeColFoot.doc"); - oddEven = openSampleFile("PageSpecificHeadFoot.doc"); - diffFirst = openSampleFile("DiffFirstPageHeadFoot.doc"); - unicode = openSampleFile("HeaderFooterUnicode.doc"); - withFields = openSampleFile("HeaderWithMacros.doc"); - } - - @Test - void testNone() { - HeaderStories hs = new HeaderStories(none); - - assertNull(hs.getPlcfHdd()); - assertEquals(0, hs.getRange().text().length()); - } - - @Test - void testHeader() { - HeaderStories hs = new HeaderStories(header); - - assertEquals(60, hs.getRange().text().length()); - - // Should have the usual 6 separaters - // Then all 6 of the different header/footer kinds - // Finally a terminater - assertEquals(13, hs.getPlcfHdd().length()); - - assertEquals(215, hs.getRange().getStartOffset()); - - assertEquals(0, hs.getPlcfHdd().getProperty(0).getStart()); - assertEquals(3, hs.getPlcfHdd().getProperty(1).getStart()); - assertEquals(6, hs.getPlcfHdd().getProperty(2).getStart()); - assertEquals(6, hs.getPlcfHdd().getProperty(3).getStart()); - assertEquals(9, hs.getPlcfHdd().getProperty(4).getStart()); - assertEquals(12, hs.getPlcfHdd().getProperty(5).getStart()); - - assertEquals(12, hs.getPlcfHdd().getProperty(6).getStart()); - assertEquals(12, hs.getPlcfHdd().getProperty(7).getStart()); - assertEquals(59, hs.getPlcfHdd().getProperty(8).getStart()); - assertEquals(59, hs.getPlcfHdd().getProperty(9).getStart()); - assertEquals(59, hs.getPlcfHdd().getProperty(10).getStart()); - assertEquals(59, hs.getPlcfHdd().getProperty(11).getStart()); - - assertEquals(59, hs.getPlcfHdd().getProperty(12).getStart()); - - assertEquals("\u0003\r\r", hs.getFootnoteSeparator()); - assertEquals("\u0004\r\r", hs.getFootnoteContSeparator()); - assertEquals("", hs.getFootnoteContNote()); - assertEquals("\u0003\r\r", hs.getEndnoteSeparator()); - assertEquals("\u0004\r\r", hs.getEndnoteContSeparator()); - assertEquals("", hs.getEndnoteContNote()); - - assertEquals("", hs.getFirstHeader()); - assertEquals("", hs.getEvenHeader()); - assertEquals("First header column!\tMid header Right header!\r\r", hs.getOddHeader()); - - assertEquals("", hs.getFirstFooter()); - assertEquals("", hs.getEvenFooter()); - assertEquals("", hs.getOddFooter()); - } - - @Test - void testFooter() { - HeaderStories hs = new HeaderStories(footer); - - assertEquals("", hs.getFirstHeader()); - assertEquals("", hs.getEvenHeader()); - assertEquals("", hs.getOddHeader()); // Was \r\r but gets emptied - - assertEquals("", hs.getFirstFooter()); - assertEquals("", hs.getEvenFooter()); - assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getOddFooter()); - } - - @Test - void testHeaderFooter() { - HeaderStories hs = new HeaderStories(headerFooter); - - assertEquals("", hs.getFirstHeader()); - assertEquals("", hs.getEvenHeader()); - assertEquals("I am some simple header text here\r\r\r", hs.getOddHeader()); - - assertEquals("", hs.getFirstFooter()); - assertEquals("", hs.getEvenFooter()); - assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getOddFooter()); - } - - @Test - void testOddEven() { - HeaderStories hs = new HeaderStories(oddEven); - - assertEquals("", hs.getFirstHeader()); - assertEquals("[This is an Even Page, with a Header]\u0007August 20, 2008\u0007\u0007\r\r", - hs.getEvenHeader()); - assertEquals("August 20, 2008\u0007[ODD Page Header text]\u0007\u0007\r\r", hs - .getOddHeader()); - - assertEquals("", hs.getFirstFooter()); - assertEquals( - "\u0007Page \u0013 PAGE \\* MERGEFORMAT \u00142\u0015\u0007\u0007\u0007\u0007\u0007\u0007\u0007This is a simple footer on the second page\r\r", - hs.getEvenFooter()); - assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getOddFooter()); - - assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getFooter(1)); - assertEquals( - "\u0007Page \u0013 PAGE \\* MERGEFORMAT \u00142\u0015\u0007\u0007\u0007\u0007\u0007\u0007\u0007This is a simple footer on the second page\r\r", - hs.getFooter(2)); - assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getFooter(3)); - } - - @Test - void testFirst() { - HeaderStories hs = new HeaderStories(diffFirst); - - assertEquals("I am the header on the first page, and I\u2019m nice and simple\r\r", hs - .getFirstHeader()); - assertEquals("", hs.getEvenHeader()); - assertEquals("First header column!\tMid header Right header!\r\r", hs.getOddHeader()); - - assertEquals("The footer of the first page\r\r", hs.getFirstFooter()); - assertEquals("", hs.getEvenFooter()); - assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getOddFooter()); - - assertEquals("The footer of the first page\r\r", hs.getFooter(1)); - assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getFooter(2)); - assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getFooter(3)); - } - - @Test - void testUnicode() { - HeaderStories hs = new HeaderStories(unicode); - - assertEquals("", hs.getFirstHeader()); - assertEquals("", hs.getEvenHeader()); - assertEquals("This is a simple header, with a \u20ac euro symbol in it.\r\r\r", hs - .getOddHeader()); - - assertEquals("", hs.getFirstFooter()); - assertEquals("", hs.getEvenFooter()); - assertEquals("The footer, with Moli\u00e8re, has Unicode in it.\r\r", hs.getOddFooter()); - } - - @Test - void testWithFields() { - HeaderStories hs = new HeaderStories(withFields); - assertFalse(hs.areFieldsStripped()); - - assertEquals( - "HEADER GOES HERE. 8/12/2008 \u0013 AUTHOR \\* MERGEFORMAT \u0014Eric Roch\u0015\r\r\r", - hs.getOddHeader()); - - // Now turn on stripping - hs.setAreFieldsStripped(true); - assertEquals("HEADER GOES HERE. 8/12/2008 Eric Roch\r\r\r", hs.getOddHeader()); - } + none = openSampleFile("NoHeadFoot.doc"); + header = openSampleFile("ThreeColHead.doc"); + footer = openSampleFile("ThreeColFoot.doc"); + headerFooter = openSampleFile("SimpleHeadThreeColFoot.doc"); + oddEven = openSampleFile("PageSpecificHeadFoot.doc"); + diffFirst = openSampleFile("DiffFirstPageHeadFoot.doc"); + unicode = openSampleFile("HeaderFooterUnicode.doc"); + withFields = openSampleFile("HeaderWithMacros.doc"); + } + + @Test + void testNone() { + HeaderStories hs = new HeaderStories(none); + + assertNull(hs.getPlcfHdd()); + assertEquals(0, hs.getRange().text().length()); + } + + @Test + void testHeader() { + HeaderStories hs = new HeaderStories(header); + + assertEquals(60, hs.getRange().text().length()); + + // Should have the usual 6 separaters + // Then all 6 of the different header/footer kinds + // Finally a terminater + assertEquals(13, hs.getPlcfHdd().length()); + + assertEquals(215, hs.getRange().getStartOffset()); + + assertEquals(0, hs.getPlcfHdd().getProperty(0).getStart()); + assertEquals(3, hs.getPlcfHdd().getProperty(1).getStart()); + assertEquals(6, hs.getPlcfHdd().getProperty(2).getStart()); + assertEquals(6, hs.getPlcfHdd().getProperty(3).getStart()); + assertEquals(9, hs.getPlcfHdd().getProperty(4).getStart()); + assertEquals(12, hs.getPlcfHdd().getProperty(5).getStart()); + + assertEquals(12, hs.getPlcfHdd().getProperty(6).getStart()); + assertEquals(12, hs.getPlcfHdd().getProperty(7).getStart()); + assertEquals(59, hs.getPlcfHdd().getProperty(8).getStart()); + assertEquals(59, hs.getPlcfHdd().getProperty(9).getStart()); + assertEquals(59, hs.getPlcfHdd().getProperty(10).getStart()); + assertEquals(59, hs.getPlcfHdd().getProperty(11).getStart()); + + assertEquals(59, hs.getPlcfHdd().getProperty(12).getStart()); + + assertEquals("\u0003\r\r", hs.getFootnoteSeparator()); + assertEquals("\u0004\r\r", hs.getFootnoteContSeparator()); + assertEquals("", hs.getFootnoteContNote()); + assertEquals("\u0003\r\r", hs.getEndnoteSeparator()); + assertEquals("\u0004\r\r", hs.getEndnoteContSeparator()); + assertEquals("", hs.getEndnoteContNote()); + + assertEquals("", hs.getFirstHeader()); + assertEquals("", hs.getEvenHeader()); + assertEquals("First header column!\tMid header Right header!\r\r", hs.getOddHeader()); + + assertEquals("", hs.getFirstFooter()); + assertEquals("", hs.getEvenFooter()); + assertEquals("", hs.getOddFooter()); + } + + @Test + void testFooter() { + HeaderStories hs = new HeaderStories(footer); + + assertEquals("", hs.getFirstHeader()); + assertEquals("", hs.getEvenHeader()); + assertEquals("", hs.getOddHeader()); // Was \r\r but gets emptied + + assertEquals("", hs.getFirstFooter()); + assertEquals("", hs.getEvenFooter()); + assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getOddFooter()); + } + + @Test + void testHeaderFooter() { + HeaderStories hs = new HeaderStories(headerFooter); + + assertEquals("", hs.getFirstHeader()); + assertEquals("", hs.getEvenHeader()); + assertEquals("I am some simple header text here\r\r\r", hs.getOddHeader()); + + assertEquals("", hs.getFirstFooter()); + assertEquals("", hs.getEvenFooter()); + assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getOddFooter()); + } + + @Test + void testOddEven() { + HeaderStories hs = new HeaderStories(oddEven); + + assertEquals("", hs.getFirstHeader()); + assertEquals("[This is an Even Page, with a Header]\u0007August 20, 2008\u0007\u0007\r\r", + hs.getEvenHeader()); + assertEquals("August 20, 2008\u0007[ODD Page Header text]\u0007\u0007\r\r", hs + .getOddHeader()); + + assertEquals("", hs.getFirstFooter()); + assertEquals( + "\u0007Page \u0013 PAGE \\* MERGEFORMAT \u00142\u0015\u0007\u0007\u0007\u0007\u0007\u0007\u0007This is a simple footer on the second page\r\r", + hs.getEvenFooter()); + assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getOddFooter()); + + assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getFooter(1)); + assertEquals( + "\u0007Page \u0013 PAGE \\* MERGEFORMAT \u00142\u0015\u0007\u0007\u0007\u0007\u0007\u0007\u0007This is a simple footer on the second page\r\r", + hs.getFooter(2)); + assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getFooter(3)); + } + + @Test + void testFirst() { + HeaderStories hs = new HeaderStories(diffFirst); + + assertEquals("I am the header on the first page, and I\u2019m nice and simple\r\r", hs + .getFirstHeader()); + assertEquals("", hs.getEvenHeader()); + assertEquals("First header column!\tMid header Right header!\r\r", hs.getOddHeader()); + + assertEquals("The footer of the first page\r\r", hs.getFirstFooter()); + assertEquals("", hs.getEvenFooter()); + assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getOddFooter()); + + assertEquals("The footer of the first page\r\r", hs.getFooter(1)); + assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getFooter(2)); + assertEquals("Footer Left\tFooter Middle Footer Right\r\r", hs.getFooter(3)); + } + + @Test + void testUnicode() { + HeaderStories hs = new HeaderStories(unicode); + + assertEquals("", hs.getFirstHeader()); + assertEquals("", hs.getEvenHeader()); + assertEquals("This is a simple header, with a \u20ac euro symbol in it.\r\r\r", hs + .getOddHeader()); + + assertEquals("", hs.getFirstFooter()); + assertEquals("", hs.getEvenFooter()); + assertEquals("The footer, with Moli\u00e8re, has Unicode in it.\r\r", hs.getOddFooter()); + } + + @Test + void testWithFields() { + HeaderStories hs = new HeaderStories(withFields); + assertFalse(hs.areFieldsStripped()); + + assertEquals( + "HEADER GOES HERE. 8/12/2008 \u0013 AUTHOR \\* MERGEFORMAT \u0014Eric Roch\u0015\r\r\r", + hs.getOddHeader()); + + // Now turn on stripping + hs.setAreFieldsStripped(true); + assertEquals("HEADER GOES HERE. 8/12/2008 Eric Roch\r\r\r", hs.getOddHeader()); + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeDelete.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeDelete.java index 1b49b3883f..840a45bae8 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeDelete.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeDelete.java @@ -27,217 +27,217 @@ import org.apache.poi.hwpf.model.PAPX; import org.junit.jupiter.api.Test; /** - * Test to see if Range.delete() works even if the Range contains a - * CharacterRun that uses Unicode characters. + * Test to see if Range.delete() works even if the Range contains a + * CharacterRun that uses Unicode characters. */ public final class TestRangeDelete { - // u201c and u201d are "smart-quotes" - private static final String introText = - "Introduction\r"; - private static final String fillerText = - "${delete} This is an MS-Word 97 formatted document created using NeoOffice v. 2.2.4 Patch 0 (OpenOffice.org v. 2.2.1).\r"; - private static final String originalText = - "It is used to confirm that text delete works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the ${organization} ${delete} and all the POI contributors for their assistance in this matter.\r"; - private static final String lastText = - "Thank you, ${organization} ${delete}!\r"; - private static final String searchText = "${delete}"; - private static final String expectedText1 = " This is an MS-Word 97 formatted document created using NeoOffice v. 2.2.4 Patch 0 (OpenOffice.org v. 2.2.1).\r"; - private static final String expectedText2 = - "It is used to confirm that text delete works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the ${organization} and all the POI contributors for their assistance in this matter.\r"; - private static final String expectedText3 = "Thank you, ${organization} !\r"; - - private static final String illustrativeDocFile = "testRangeDelete.doc"; - - /** - * Test just opening the files - */ - @Test - void testOpen() throws IOException { - try (HWPFDocument doc = openSampleFile(illustrativeDocFile)) { - assertEquals(5, doc.getParagraphTable().getParagraphs().size()); - } - } - - /** - * Test (more "confirm" than test) that we have the general structure that we expect to have. - */ - @Test - void testDocStructure() throws IOException { + // u201c and u201d are "smart-quotes" + private static final String introText = + "Introduction\r"; + private static final String fillerText = + "${delete} This is an MS-Word 97 formatted document created using NeoOffice v. 2.2.4 Patch 0 (OpenOffice.org v. 2.2.1).\r"; + private static final String originalText = + "It is used to confirm that text delete works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the ${organization} ${delete} and all the POI contributors for their assistance in this matter.\r"; + private static final String lastText = + "Thank you, ${organization} ${delete}!\r"; + private static final String searchText = "${delete}"; + private static final String expectedText1 = " This is an MS-Word 97 formatted document created using NeoOffice v. 2.2.4 Patch 0 (OpenOffice.org v. 2.2.1).\r"; + private static final String expectedText2 = + "It is used to confirm that text delete works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the ${organization} and all the POI contributors for their assistance in this matter.\r"; + private static final String expectedText3 = "Thank you, ${organization} !\r"; + + private static final String illustrativeDocFile = "testRangeDelete.doc"; + + /** + * Test just opening the files + */ + @Test + void testOpen() throws IOException { + try (HWPFDocument doc = openSampleFile(illustrativeDocFile)) { + assertEquals(5, doc.getParagraphTable().getParagraphs().size()); + } + } + + /** + * Test (more "confirm" than test) that we have the general structure that we expect to have. + */ + @Test + void testDocStructure() throws IOException { - try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { - Range range; - Section section; - Paragraph para; - PAPX paraDef; - - // First, check overall - range = daDoc.getOverallRange(); - assertEquals(1, range.numSections()); - assertEquals(5, range.numParagraphs()); - - - // Now, onto just the doc bit - range = daDoc.getRange(); - - assertEquals(1, range.numSections()); - assertEquals(1, daDoc.getSectionTable().getSections().size()); - section = range.getSection(0); - - assertEquals(5, section.numParagraphs()); - - para = section.getParagraph(0); - assertEquals(1, para.numCharacterRuns()); - assertEquals(introText, para.text()); - - para = section.getParagraph(1); - assertEquals(5, para.numCharacterRuns()); - assertEquals(fillerText, para.text()); + try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { + Range range; + Section section; + Paragraph para; + PAPX paraDef; + + // First, check overall + range = daDoc.getOverallRange(); + assertEquals(1, range.numSections()); + assertEquals(5, range.numParagraphs()); + + + // Now, onto just the doc bit + range = daDoc.getRange(); + + assertEquals(1, range.numSections()); + assertEquals(1, daDoc.getSectionTable().getSections().size()); + section = range.getSection(0); + + assertEquals(5, section.numParagraphs()); + + para = section.getParagraph(0); + assertEquals(1, para.numCharacterRuns()); + assertEquals(introText, para.text()); + + para = section.getParagraph(1); + assertEquals(5, para.numCharacterRuns()); + assertEquals(fillerText, para.text()); - paraDef = daDoc.getParagraphTable().getParagraphs().get(2); - assertEquals(132, paraDef.getStart()); - assertEquals(400, paraDef.getEnd()); - - para = section.getParagraph(2); - assertEquals(5, para.numCharacterRuns()); - assertEquals(originalText, para.text()); - - - paraDef = daDoc.getParagraphTable().getParagraphs().get(3); - assertEquals(400, paraDef.getStart()); - assertEquals(438, paraDef.getEnd()); - - para = section.getParagraph(3); - assertEquals(1, para.numCharacterRuns()); - assertEquals(lastText, para.text()); + paraDef = daDoc.getParagraphTable().getParagraphs().get(2); + assertEquals(132, paraDef.getStart()); + assertEquals(400, paraDef.getEnd()); + + para = section.getParagraph(2); + assertEquals(5, para.numCharacterRuns()); + assertEquals(originalText, para.text()); + + + paraDef = daDoc.getParagraphTable().getParagraphs().get(3); + assertEquals(400, paraDef.getStart()); + assertEquals(438, paraDef.getEnd()); + + para = section.getParagraph(3); + assertEquals(1, para.numCharacterRuns()); + assertEquals(lastText, para.text()); - // Check things match on text length - assertEquals(439, range.text().length()); - assertEquals(439, section.text().length()); - assertEquals(439, - section.getParagraph(0).text().length() + - section.getParagraph(1).text().length() + - section.getParagraph(2).text().length() + - section.getParagraph(3).text().length() + - section.getParagraph(4).text().length() - ); - } - } + // Check things match on text length + assertEquals(439, range.text().length()); + assertEquals(439, section.text().length()); + assertEquals(439, + section.getParagraph(0).text().length() + + section.getParagraph(1).text().length() + + section.getParagraph(2).text().length() + + section.getParagraph(3).text().length() + + section.getParagraph(4).text().length() + ); + } + } - /** - * Test that we can delete text (one instance) from our Range with Unicode text. - */ - @Test - void testRangeDeleteOne() throws IOException { - try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { + /** + * Test that we can delete text (one instance) from our Range with Unicode text. + */ + @Test + void testRangeDeleteOne() throws IOException { + try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { - Range range = daDoc.getOverallRange(); - assertEquals(1, range.numSections()); + Range range = daDoc.getOverallRange(); + assertEquals(1, range.numSections()); - Section section = range.getSection(0); - assertEquals(5, section.numParagraphs()); + Section section = range.getSection(0); + assertEquals(5, section.numParagraphs()); - Paragraph para = section.getParagraph(2); + Paragraph para = section.getParagraph(2); - String text = para.text(); - assertEquals(originalText, text); + String text = para.text(); + assertEquals(originalText, text); - int offset = text.indexOf(searchText); - assertEquals(192, offset); + int offset = text.indexOf(searchText); + assertEquals(192, offset); - int absOffset = para.getStartOffset() + offset; - Range subRange = new Range(absOffset, (absOffset + searchText.length()), para.getDocument()); + int absOffset = para.getStartOffset() + offset; + Range subRange = new Range(absOffset, (absOffset + searchText.length()), para.getDocument()); - assertEquals(searchText, subRange.text()); + assertEquals(searchText, subRange.text()); - subRange.delete(); - daDoc.getOverallRange().sanityCheck(); - daDoc.getRange().sanityCheck(); + subRange.delete(); + daDoc.getOverallRange().sanityCheck(); + daDoc.getRange().sanityCheck(); - // we need to let the model re-calculate the Range before we evaluate it - range = daDoc.getRange(); + // we need to let the model re-calculate the Range before we evaluate it + range = daDoc.getRange(); - assertEquals(1, range.numSections()); - section = range.getSection(0); + assertEquals(1, range.numSections()); + section = range.getSection(0); - assertEquals(5, section.numParagraphs()); - para = section.getParagraph(2); + assertEquals(5, section.numParagraphs()); + para = section.getParagraph(2); - text = para.text(); - assertEquals(expectedText2, text); + text = para.text(); + assertEquals(expectedText2, text); - // this can lead to a StringBufferOutOfBoundsException, so we will add it - // even though we don't have an assertion for it - Range daRange = daDoc.getRange(); - daRange.sanityCheck(); - daRange.text(); - } - } + // this can lead to a StringBufferOutOfBoundsException, so we will add it + // even though we don't have an assertion for it + Range daRange = daDoc.getRange(); + daRange.sanityCheck(); + daRange.text(); + } + } - /** - * Test that we can delete text (all instances of) from our Range with Unicode text. - */ - @Test - void testRangeDeleteAll() throws IOException { - try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { + /** + * Test that we can delete text (all instances of) from our Range with Unicode text. + */ + @Test + void testRangeDeleteAll() throws IOException { + try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { - Range range = daDoc.getRange(); - assertEquals(1, range.numSections()); + Range range = daDoc.getRange(); + assertEquals(1, range.numSections()); - Section section = range.getSection(0); - assertEquals(5, section.numParagraphs()); + Section section = range.getSection(0); + assertEquals(5, section.numParagraphs()); - Paragraph para = section.getParagraph(2); + Paragraph para = section.getParagraph(2); - String text = para.text(); - assertEquals(originalText, text); + String text = para.text(); + assertEquals(originalText, text); - boolean keepLooking = true; - while (keepLooking) { - // Reload the range every time - range = daDoc.getRange(); - int offset = range.text().indexOf(searchText); - if (offset >= 0) { + boolean keepLooking = true; + while (keepLooking) { + // Reload the range every time + range = daDoc.getRange(); + int offset = range.text().indexOf(searchText); + if (offset >= 0) { - int absOffset = range.getStartOffset() + offset; + int absOffset = range.getStartOffset() + offset; - Range subRange = new Range( - absOffset, (absOffset + searchText.length()), range.getDocument()); + Range subRange = new Range( + absOffset, (absOffset + searchText.length()), range.getDocument()); - assertEquals(searchText, subRange.text()); + assertEquals(searchText, subRange.text()); - subRange.delete(); + subRange.delete(); - } else { - keepLooking = false; - } - } + } else { + keepLooking = false; + } + } - // we need to let the model re-calculate the Range before we use it - range = daDoc.getRange(); + // we need to let the model re-calculate the Range before we use it + range = daDoc.getRange(); - assertEquals(1, range.numSections()); - section = range.getSection(0); + assertEquals(1, range.numSections()); + section = range.getSection(0); - assertEquals(5, section.numParagraphs()); + assertEquals(5, section.numParagraphs()); - para = section.getParagraph(0); - text = para.text(); - assertEquals(introText, text); + para = section.getParagraph(0); + text = para.text(); + assertEquals(introText, text); - para = section.getParagraph(1); - text = para.text(); - assertEquals(expectedText1, text); + para = section.getParagraph(1); + text = para.text(); + assertEquals(expectedText1, text); - para = section.getParagraph(2); - text = para.text(); - assertEquals(expectedText2, text); + para = section.getParagraph(2); + text = para.text(); + assertEquals(expectedText2, text); - para = section.getParagraph(3); - text = para.text(); - assertEquals(expectedText3, text); - } - } + para = section.getParagraph(3); + text = para.text(); + assertEquals(expectedText3, text); + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeInsertion.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeInsertion.java index e8a9259460..ff5010c07f 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeInsertion.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeInsertion.java @@ -26,97 +26,97 @@ import org.apache.poi.hwpf.HWPFDocument; import org.junit.jupiter.api.Test; /** - * Test to see if Range.insertBefore() works even if the Range contains a - * CharacterRun that uses Unicode characters. + * Test to see if Range.insertBefore() works even if the Range contains a + * CharacterRun that uses Unicode characters. * * TODO - re-enable me when unicode paragraph stuff is fixed! */ public final class TestRangeInsertion { - // u201c and u201d are "smart-quotes" - private static final String originalText = - "It is used to confirm that text insertion works even if Unicode characters (such as \u201c\u2014\u201d " + - "(U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present.\r"; - private static final String textToInsert = "Look at me! I'm cool! "; - private static final int insertionPoint = 122; - - private static final String illustrativeDocFile = "testRangeInsertion.doc"; - - /** - * Test just opening the files - */ - @Test - void testOpen() throws IOException { - try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { - assertEquals(3, daDoc.getParagraphTable().getParagraphs().size()); - } - } - - /** - * Test (more "confirm" than test) that we have the general structure that we expect to have. - */ - @Test - void testDocStructure() throws IOException { - try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { - - Range range = daDoc.getRange(); - - assertEquals(1, range.numSections()); - Section section = range.getSection(0); - - assertEquals(3, section.numParagraphs()); - Paragraph para = section.getParagraph(2); - assertEquals(originalText, para.text()); - - assertEquals(3, para.numCharacterRuns()); - String text = - para.getCharacterRun(0).text() + - para.getCharacterRun(1).text() + - para.getCharacterRun(2).text(); - - assertEquals(originalText, text); - - assertEquals(insertionPoint, para.getStartOffset()); - } - } - - /** - * Test that we can insert text in our CharacterRun with Unicode text. - */ - @Test - void testRangeInsertion() throws IOException { - try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { - -// if (false) { // TODO - delete or resurrect this code -// Range range = daDoc.getRange(); -// Section section = range.getSection(0); -// Paragraph para = section.getParagraph(2); -// String text = para.getCharacterRun(0).text() + para.getCharacterRun(1).text() + -// para.getCharacterRun(2).text(); + // u201c and u201d are "smart-quotes" + private static final String originalText = + "It is used to confirm that text insertion works even if Unicode characters (such as \u201c\u2014\u201d " + + "(U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present.\r"; + private static final String textToInsert = "Look at me! I'm cool! "; + private static final int insertionPoint = 122; + + private static final String illustrativeDocFile = "testRangeInsertion.doc"; + + /** + * Test just opening the files + */ + @Test + void testOpen() throws IOException { + try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { + assertEquals(3, daDoc.getParagraphTable().getParagraphs().size()); + } + } + + /** + * Test (more "confirm" than test) that we have the general structure that we expect to have. + */ + @Test + void testDocStructure() throws IOException { + try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { + + Range range = daDoc.getRange(); + + assertEquals(1, range.numSections()); + Section section = range.getSection(0); + + assertEquals(3, section.numParagraphs()); + Paragraph para = section.getParagraph(2); + assertEquals(originalText, para.text()); + + assertEquals(3, para.numCharacterRuns()); + String text = + para.getCharacterRun(0).text() + + para.getCharacterRun(1).text() + + para.getCharacterRun(2).text(); + + assertEquals(originalText, text); + + assertEquals(insertionPoint, para.getStartOffset()); + } + } + + /** + * Test that we can insert text in our CharacterRun with Unicode text. + */ + @Test + void testRangeInsertion() throws IOException { + try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { + +// if (false) { // TODO - delete or resurrect this code +// Range range = daDoc.getRange(); +// Section section = range.getSection(0); +// Paragraph para = section.getParagraph(2); +// String text = para.getCharacterRun(0).text() + para.getCharacterRun(1).text() + +// para.getCharacterRun(2).text(); // -// System.out.println(text); -// } +// System.out.println(text); +// } - Range range = new Range(insertionPoint, (insertionPoint + 2), daDoc); - range.insertBefore(textToInsert); + Range range = new Range(insertionPoint, (insertionPoint + 2), daDoc); + range.insertBefore(textToInsert); - // we need to let the model re-calculate the Range before we evaluate it - range = daDoc.getRange(); + // we need to let the model re-calculate the Range before we evaluate it + range = daDoc.getRange(); - assertEquals(1, range.numSections()); - Section section = range.getSection(0); + assertEquals(1, range.numSections()); + Section section = range.getSection(0); - assertEquals(3, section.numParagraphs()); - Paragraph para = section.getParagraph(2); - assertEquals((textToInsert + originalText), para.text()); + assertEquals(3, section.numParagraphs()); + Paragraph para = section.getParagraph(2); + assertEquals((textToInsert + originalText), para.text()); - assertEquals(3, para.numCharacterRuns()); - String text = - para.getCharacterRun(0).text() + - para.getCharacterRun(1).text() + - para.getCharacterRun(2).text(); + assertEquals(3, para.numCharacterRuns()); + String text = + para.getCharacterRun(0).text() + + para.getCharacterRun(1).text() + + para.getCharacterRun(2).text(); - assertEquals((textToInsert + originalText), text); - } - } + assertEquals((textToInsert + originalText), text); + } + } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeProperties.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeProperties.java index 21514bd246..cdb9663f34 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeProperties.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeProperties.java @@ -261,7 +261,7 @@ public final class TestRangeProperties { p1_parts[2].length() + 1, p2.getEnd() ); - } + } /** * Tests the paragraph text of a unicode document diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java index 2cecbe8bd6..32b1cf45a3 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java @@ -26,131 +26,131 @@ import org.apache.poi.hwpf.HWPFDocument; import org.junit.jupiter.api.Test; /** - * Test to see if Range.replaceText() works even if the Range contains a - * CharacterRun that uses Unicode characters. + * Test to see if Range.replaceText() works even if the Range contains a + * CharacterRun that uses Unicode characters. * * TODO - re-enable me when unicode paragraph stuff is fixed! */ public final class TestRangeReplacement { - // u201c and u201d are "smart-quotes" - private static final String originalText = - "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the ${organization} and all the POI contributors for their assistance in this matter.\r"; - private static final String searchText = "${organization}"; - private static final String replacementText = "Apache Software Foundation"; - private static final String expectedText2 = - "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the Apache Software Foundation and all the POI contributors for their assistance in this matter.\r"; - private static final String expectedText3 = "Thank you, Apache Software Foundation!\r"; + // u201c and u201d are "smart-quotes" + private static final String originalText = + "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the ${organization} and all the POI contributors for their assistance in this matter.\r"; + private static final String searchText = "${organization}"; + private static final String replacementText = "Apache Software Foundation"; + private static final String expectedText2 = + "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the Apache Software Foundation and all the POI contributors for their assistance in this matter.\r"; + private static final String expectedText3 = "Thank you, Apache Software Foundation!\r"; - private static final String illustrativeDocFile = "testRangeReplacement.doc"; + private static final String illustrativeDocFile = "testRangeReplacement.doc"; - /** - * Test just opening the files - */ - void testOpen() { - openSampleFile(illustrativeDocFile); - } + /** + * Test just opening the files + */ + void testOpen() { + openSampleFile(illustrativeDocFile); + } - /** - * Test (more "confirm" than test) that we have the general structure that we expect to have. - */ - @Test - void testDocStructure() throws IOException { - try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { - - Range range = daDoc.getRange(); - assertEquals(414, range.text().length()); - - assertEquals(1, range.numSections()); - Section section = range.getSection(0); - assertEquals(414, section.text().length()); - - assertEquals(5, section.numParagraphs()); - Paragraph para = section.getParagraph(2); - - assertEquals(5, para.numCharacterRuns()); - String text = - para.getCharacterRun(0).text() + - para.getCharacterRun(1).text() + - para.getCharacterRun(2).text() + - para.getCharacterRun(3).text() + - para.getCharacterRun(4).text(); - - assertEquals(originalText, text); - } - } - - /** - * Test that we can replace text in our Range with Unicode text. - */ - @Test - void testRangeReplacementOne() throws IOException { - try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { - - // Has one section - Range range = daDoc.getRange(); - assertEquals(1, range.numSections()); - - // The first section has 5 paragraphs - Section section = range.getSection(0); - assertEquals(5, section.numParagraphs()); - - - // Change some text - Paragraph para = section.getParagraph(2); - - String text = para.text(); - assertEquals(originalText, text); - - int offset = text.indexOf(searchText); - assertEquals(181, offset); - - para.replaceText(searchText, replacementText, offset); - - // Ensure we still have one section, 5 paragraphs - assertEquals(1, range.numSections()); - section = range.getSection(0); - - assertEquals(5, section.numParagraphs()); - para = section.getParagraph(2); - - // Ensure the text is what we should now have - text = para.text(); - assertEquals(expectedText2, text); - } - } - - /** - * Test that we can replace text in our Range with Unicode text. - */ - @Test - void testRangeReplacementAll() throws IOException { - try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { - - Range range = daDoc.getRange(); - assertEquals(1, range.numSections()); - - Section section = range.getSection(0); - assertEquals(5, section.numParagraphs()); - - Paragraph para = section.getParagraph(2); - - String text = para.text(); - assertEquals(originalText, text); - - range.replaceText(searchText, replacementText); + /** + * Test (more "confirm" than test) that we have the general structure that we expect to have. + */ + @Test + void testDocStructure() throws IOException { + try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { + + Range range = daDoc.getRange(); + assertEquals(414, range.text().length()); + + assertEquals(1, range.numSections()); + Section section = range.getSection(0); + assertEquals(414, section.text().length()); + + assertEquals(5, section.numParagraphs()); + Paragraph para = section.getParagraph(2); + + assertEquals(5, para.numCharacterRuns()); + String text = + para.getCharacterRun(0).text() + + para.getCharacterRun(1).text() + + para.getCharacterRun(2).text() + + para.getCharacterRun(3).text() + + para.getCharacterRun(4).text(); + + assertEquals(originalText, text); + } + } + + /** + * Test that we can replace text in our Range with Unicode text. + */ + @Test + void testRangeReplacementOne() throws IOException { + try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { + + // Has one section + Range range = daDoc.getRange(); + assertEquals(1, range.numSections()); + + // The first section has 5 paragraphs + Section section = range.getSection(0); + assertEquals(5, section.numParagraphs()); + + + // Change some text + Paragraph para = section.getParagraph(2); + + String text = para.text(); + assertEquals(originalText, text); + + int offset = text.indexOf(searchText); + assertEquals(181, offset); + + para.replaceText(searchText, replacementText, offset); + + // Ensure we still have one section, 5 paragraphs + assertEquals(1, range.numSections()); + section = range.getSection(0); + + assertEquals(5, section.numParagraphs()); + para = section.getParagraph(2); + + // Ensure the text is what we should now have + text = para.text(); + assertEquals(expectedText2, text); + } + } + + /** + * Test that we can replace text in our Range with Unicode text. + */ + @Test + void testRangeReplacementAll() throws IOException { + try (HWPFDocument daDoc = openSampleFile(illustrativeDocFile)) { + + Range range = daDoc.getRange(); + assertEquals(1, range.numSections()); + + Section section = range.getSection(0); + assertEquals(5, section.numParagraphs()); + + Paragraph para = section.getParagraph(2); + + String text = para.text(); + assertEquals(originalText, text); + + range.replaceText(searchText, replacementText); - assertEquals(1, range.numSections()); - section = range.getSection(0); - assertEquals(5, section.numParagraphs()); + assertEquals(1, range.numSections()); + section = range.getSection(0); + assertEquals(5, section.numParagraphs()); - para = section.getParagraph(2); - text = para.text(); - assertEquals(expectedText2, text); + para = section.getParagraph(2); + text = para.text(); + assertEquals(expectedText2, text); - para = section.getParagraph(3); - text = para.text(); - assertEquals(expectedText3, text); - } - } + para = section.getParagraph(3); + text = para.text(); + assertEquals(expectedText3, text); + } + } } |