--- src/scratchpad/src/org/apache/poi/hslf/record/DocInfoListContainer.java (nonexistent) +++ src/scratchpad/src/org/apache/poi/hslf/record/DocInfoListContainer.java (working copy) @@ -0,0 +1,84 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import java.io.IOException; +import java.io.OutputStream; + +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 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 = new byte[8]; + System.arraycopy(source,start,_header,0,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 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); + } + +} --- src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java (revision 1738651) +++ src/scratchpad/src/org/apache/poi/hslf/record/ExOleObjStg.java (working copy) @@ -144,6 +144,15 @@ } /** + * Gets the record instance from the header + * + * @return record instance + */ + public int getRecordInstance() { + return (LittleEndian.getUShort(_header, 0) >>> 4); + } + + /** * Write the contents of the record back, so it can be written * to disk. * --- src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java (revision 1738651) +++ src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java (working copy) @@ -47,8 +47,8 @@ ViewInfo(1020,null), ViewInfoAtom(1021,null), SlideViewInfoAtom(1022,null), - VBAInfo(1023,null), - VBAInfoAtom(1024,null), + VBAInfo(1023,VBAInfoContainer.class), + VBAInfoAtom(1024,VBAInfoAtom.class), SSDocInfoAtom(1025,null), Summary(1026,null), DocRoutingSlip(1030,null), @@ -63,7 +63,7 @@ NamedShowSlides(1042,null), SheetProperties(1044,null), RoundTripCustomTableStyles12Atom(1064,null), - List(2000,null), + List(2000,DocInfoListContainer.class), FontCollection(2005,FontCollection.class), BookmarkCollection(2019,null), SoundCollection(2020,SoundCollection.class), --- src/scratchpad/src/org/apache/poi/hslf/record/VBAInfoAtom.java (nonexistent) +++ src/scratchpad/src/org/apache/poi/hslf/record/VBAInfoAtom.java (working copy) @@ -0,0 +1,117 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.util.LittleEndian; + +/** + * An atom record that specifies a reference to the VBA project storage. + */ +public final class VBAInfoAtom extends RecordAtom { + private static final long _type = RecordTypes.VBAInfoAtom.typeID; + + /** + * Record header. + */ + private byte[] _header; + + /** + * Record data. + */ + private long persistIdRef; + private boolean hasMacros; + private long version; + + /** + * Constructs an empty atom - not yet supported + */ + private VBAInfoAtom() { + _header = new byte[8]; + // TODO: fix me + LittleEndian.putUInt(_header, 0, _type); + persistIdRef = 0; + hasMacros = true; + version = 2; + } + + /** + * Constructs the vba atom record from its source data. + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + public VBAInfoAtom(byte[] source, int start, int len) { + // Get the header. + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Get the record data. + persistIdRef = LittleEndian.getUInt(source, start+8); + hasMacros = (LittleEndian.getUInt(source, start+16) == 1); + version = LittleEndian.getUInt(source, start+24); + } + /** + * Gets the record type. + * @return the record type. + */ + public long getRecordType() { return _type; } + + /** + * Write the contents of the record back, so it can be written + * to disk + * + * @param out the output stream to write to. + * @throws java.io.IOException if an error occurs. + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + LittleEndian.putUInt(persistIdRef, out); + LittleEndian.putUInt(hasMacros ? 1 : 0, out); + LittleEndian.putUInt(version, out); + } + + public long getPersistIdRef() { + return persistIdRef; + } + + public void setPersistIdRef(long persistIdRef) { + this.persistIdRef = persistIdRef; + } + + public boolean isHasMacros() { + return hasMacros; + } + + public void setHasMacros(boolean hasMacros) { + this.hasMacros = hasMacros; + } + + public long getVersion() { + return version; + } + + public void setVersion(long version) { + this.version = version; + } + + +} --- src/scratchpad/src/org/apache/poi/hslf/record/VBAInfoContainer.java (nonexistent) +++ src/scratchpad/src/org/apache/poi/hslf/record/VBAInfoContainer.java (working copy) @@ -0,0 +1,84 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.util.LittleEndian; + +/** + * A container record that specifies VBA information for the document. + */ +public final class VBAInfoContainer extends RecordContainer { + private byte[] _header; + private static long _type = RecordTypes.VBAInfo.typeID; + + // Links to our more interesting children + + /** + * Set things up, and find our more interesting children + */ + protected VBAInfoContainer(byte[] source, int start, int len) { + // Grab the header + _header = new byte[8]; + System.arraycopy(source,start,_header,0,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 VBAInfoContainer, with blank fields - not yet supported + */ + private VBAInfoContainer() { + _header = new byte[8]; + _children = new 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 0x3FF + */ + 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); + } + +} --- src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java (revision 1738651) +++ src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java (working copy) @@ -29,8 +29,10 @@ import java.awt.geom.Path2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.text.AttributedCharacterIterator; @@ -51,12 +53,18 @@ import org.apache.poi.hslf.exceptions.OldPowerPointFormatException; import org.apache.poi.hslf.extractor.PowerPointExtractor; import org.apache.poi.hslf.model.HeadersFooters; +import org.apache.poi.hslf.record.DocInfoListContainer; import org.apache.poi.hslf.record.Document; +import org.apache.poi.hslf.record.ExOleObjStg; import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.hslf.record.SlideListWithText; import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; import org.apache.poi.hslf.record.TextHeaderAtom; +import org.apache.poi.hslf.record.VBAInfoAtom; +import org.apache.poi.hslf.record.VBAInfoContainer; import org.apache.poi.hssf.usermodel.DummyGraphics2d; +import org.apache.poi.poifs.macros.VBAMacroReader; import org.apache.poi.sl.draw.DrawFactory; import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.draw.DrawTextParagraph; @@ -72,6 +80,7 @@ import org.apache.poi.sl.usermodel.TextParagraph; import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; import org.apache.poi.sl.usermodel.TextRun; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.StringUtil; import org.apache.poi.util.Units; @@ -948,4 +957,30 @@ ppt2.close(); } + + @Test + public void macrotest() throws IOException { + HSLFSlideShow ppt = open("SimpleMacro.ppt"); + DocInfoListContainer list = (DocInfoListContainer)ppt.getDocumentRecord().findFirstOfType(RecordTypes.List.typeID); + VBAInfoContainer vbaInfo = (VBAInfoContainer)list.findFirstOfType(RecordTypes.VBAInfo.typeID); + VBAInfoAtom vbaAtom = (VBAInfoAtom)vbaInfo.findFirstOfType(RecordTypes.VBAInfoAtom.typeID); + long persistId = vbaAtom.getPersistIdRef(); + byte data[] = null; + + for (HSLFObjectData obj : ppt.getEmbeddedObjects()) { + ExOleObjStg exObj = obj.getExOleObjStg(); + if (exObj.getPersistId() == persistId) { + // compression is handled by exoleobjstg + InputStream rawData = exObj.getData(); + data = IOUtils.toByteArray(rawData); + rawData.close(); + break; + } + }; + + VBAMacroReader vbareader = new VBAMacroReader(new ByteArrayInputStream(data)); + Map bla = vbareader.readMacros(); + ppt.close(); + } + }