From 9213d605e2ef9d9a6f7ae5d1a1ef91d1d11b7b82 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Tue, 12 Aug 2008 06:55:10 +0000 Subject: [PATCH] Fix bug #45590: Header/footer extraction for .ppt files saved in Office 2007 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@685054 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/changes.xml | 1 + src/documentation/content/xdocs/status.xml | 1 + .../apache/poi/hslf/model/HeadersFooters.java | 63 +++++-- .../apache/poi/hslf/model/MasterSheet.java | 17 +- .../src/org/apache/poi/hslf/model/Sheet.java | 79 ++++++++ .../src/org/apache/poi/hslf/model/Slide.java | 16 +- .../org/apache/poi/hslf/model/TextShape.java | 2 +- .../poi/hslf/record/OEPlaceholderAtom.java | 177 +++++++++++++++--- .../apache/poi/hslf/record/RecordTypes.java | 11 ++ .../hslf/record/RoundTripHFPlaceholder12.java | 99 ++++++++++ .../apache/poi/hslf/usermodel/SlideShow.java | 28 +-- .../poi/hslf/data/headers_footers_2007.ppt | Bin 0 -> 169472 bytes .../poi/hslf/model/TestHeadersFooters.java | 106 +++++++++++ 13 files changed, 533 insertions(+), 67 deletions(-) create mode 100644 src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java create mode 100644 src/scratchpad/testcases/org/apache/poi/hslf/data/headers_footers_2007.ppt diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 62b53e5410..985db6ab9f 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + 45590 - Fix for Header/footer extraction for .ppt files saved in Office 2007 Big improvement in how HWPF handles unicode text, and more sanity checking of text ranges within HWPF Include headers and footers int he extracted text from HWPF's WordExtractor Added support to HWPF for headers and footers diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index a020a892a2..d762f1e5a5 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 45590 - Fix for Header/footer extraction for .ppt files saved in Office 2007 Big improvement in how HWPF handles unicode text, and more sanity checking of text ranges within HWPF Include headers and footers int he extracted text from HWPF's WordExtractor Added support to HWPF for headers and footers diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java b/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java index 90aee3421d..38b0dff9e2 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java @@ -32,11 +32,22 @@ public class HeadersFooters { private HeadersFootersContainer _container; private boolean _newRecord; private SlideShow _ppt; + private Sheet _sheet; + private boolean _ppt2007; - public HeadersFooters(HeadersFootersContainer rec, SlideShow ppt, boolean newRecord){ + + public HeadersFooters(HeadersFootersContainer rec, SlideShow ppt, boolean newRecord, boolean isPpt2007){ _container = rec; _newRecord = newRecord; _ppt = ppt; + _ppt2007 = isPpt2007; + } + + public HeadersFooters(HeadersFootersContainer rec, Sheet sheet, boolean newRecord, boolean isPpt2007){ + _container = rec; + _newRecord = newRecord; + _sheet = sheet; + _ppt2007 = isPpt2007; } /** @@ -45,8 +56,8 @@ public class HeadersFooters { * @return Headers's text */ public String getHeaderText(){ - CString cs = _container.getHeaderAtom(); - return cs == null ? null : cs.getText(); + CString cs = _container == null ? null : _container.getHeaderAtom(); + return getPlaceholderText(OEPlaceholderAtom.MasterHeader, cs); } /** @@ -70,8 +81,8 @@ public class HeadersFooters { * @return Footer's text */ public String getFooterText(){ - CString cs = _container.getFooterAtom(); - return cs == null ? null : cs.getText(); + CString cs = _container == null ? null : _container.getFooterAtom(); + return getPlaceholderText(OEPlaceholderAtom.MasterFooter, cs); } /** @@ -95,8 +106,8 @@ public class HeadersFooters { * @return custom user date */ public String getDateTimeText(){ - CString cs = _container.getUserDateAtom(); - return cs == null ? null : cs.getText(); + CString cs = _container == null ? null : _container.getUserDateAtom(); + return getPlaceholderText(OEPlaceholderAtom.MasterDate, cs); } /** @@ -119,7 +130,7 @@ public class HeadersFooters { * whether the footer text is displayed. */ public boolean isFooterVisible(){ - return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasFooter); + return isVisible(HeadersFootersAtom.fHasFooter, OEPlaceholderAtom.MasterFooter); } /** @@ -134,7 +145,7 @@ public class HeadersFooters { * whether the header text is displayed. */ public boolean isHeaderVisible(){ - return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasHeader); + return isVisible(HeadersFootersAtom.fHasHeader, OEPlaceholderAtom.MasterHeader); } /** @@ -149,7 +160,7 @@ public class HeadersFooters { * whether the date is displayed in the footer. */ public boolean isDateTimeVisible(){ - return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasDate); + return isVisible(HeadersFootersAtom.fHasDate, OEPlaceholderAtom.MasterDate); } /** @@ -164,7 +175,7 @@ public class HeadersFooters { * whether the custom user date is used instead of today's date. */ public boolean isUserDateVisible(){ - return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasUserDate); + return isVisible(HeadersFootersAtom.fHasUserDate, OEPlaceholderAtom.MasterDate); } /** @@ -179,7 +190,7 @@ public class HeadersFooters { * whether the slide number is displayed in the footer. */ public boolean isSlideNumberVisible(){ - return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasSlideNumber); + return isVisible(HeadersFootersAtom.fHasSlideNumber, OEPlaceholderAtom.MasterSlideNumber); } /** @@ -225,4 +236,32 @@ public class HeadersFooters { doc.addChildAfter(_container, lst); _newRecord = false; } + + private boolean isVisible(int flag, int placeholderId){ + boolean visible; + if(_ppt2007){ + Sheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0]; + TextShape placeholder = master.getPlaceholder(placeholderId); + visible = placeholder != null && placeholder.getText() != null; + } else { + visible = _container.getHeadersFootersAtom().getFlag(flag); + } + return visible; + } + + private String getPlaceholderText(int placeholderId, CString cs){ + String text = null; + if(_ppt2007){ + Sheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0]; + TextShape placeholder = master.getPlaceholder(placeholderId); + if(placeholder != null) text = placeholder.getText(); + + //default text in master placeholders is not visible + if("*".equals(text)) text = null; + } else { + text = cs == null ? null : cs.getText(); + } + return text; + } + } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java index 17c1d1c23f..501cf65bdf 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java @@ -19,6 +19,7 @@ package org.apache.poi.hslf.model; import org.apache.poi.hslf.record.SheetContainer; import org.apache.poi.hslf.record.Record; import org.apache.poi.hslf.record.RecordTypes; +import org.apache.poi.hslf.record.OEPlaceholderAtom; import org.apache.poi.hslf.model.textproperties.TextProp; /** @@ -54,20 +55,4 @@ public abstract class MasterSheet extends Sheet { return tx.getPlaceholderAtom() != null; } - /** - * Return placeholder by text type - */ - public TextShape getPlaceholder(int type){ - Shape[] shape = getShapes(); - for (int i = 0; i < shape.length; i++) { - if(shape[i] instanceof TextShape){ - TextShape tx = (TextShape)shape[i]; - TextRun run = tx.getTextRun(); - if(run != null && run.getRunType() == type){ - return tx; - } - } - } - return null; - } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java index 6eb84ca2e7..ccbc03829f 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java @@ -362,4 +362,83 @@ public abstract class Sheet { public void draw(Graphics2D graphics){ } + + /** + * Return placeholder by text type + * + * @param type type of text, See {@link org.apache.poi.hslf.record.TextHeaderAtom} + * @return TextShape or null + */ + public TextShape getPlaceholderByTextType(int type){ + Shape[] shape = getShapes(); + for (int i = 0; i < shape.length; i++) { + if(shape[i] instanceof TextShape){ + TextShape tx = (TextShape)shape[i]; + TextRun run = tx.getTextRun(); + if(run != null && run.getRunType() == type){ + return tx; + } + } + } + return null; + } + + /** + * Search text placeholer by its type + * + * @param type type of placeholder to search. See {@link org.apache.poi.hslf.record.OEPlaceholderAtom} + * @return TextShape or null + */ + public TextShape getPlaceholder(int type){ + Shape[] shape = getShapes(); + for (int i = 0; i < shape.length; i++) { + if(shape[i] instanceof TextShape){ + TextShape tx = (TextShape)shape[i]; + int placeholderId = 0; + OEPlaceholderAtom oep = tx.getPlaceholderAtom(); + if(oep != null) { + placeholderId = oep.getPlaceholderId(); + } else { + //special case for files saved in Office 2007 + RoundTripHFPlaceholder12 hldr = (RoundTripHFPlaceholder12)tx.getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID); + if(hldr != null) placeholderId = hldr.getPlaceholderId(); + } + if(placeholderId == type){ + return tx; + } + } + } + return null; + } + + /** + * Return programmable tag associated with this sheet, e.g. ___PPT12. + * + * @return programmable tag associated with this sheet. + */ + public String getProgrammableTag(){ + String tag = null; + RecordContainer progTags = (RecordContainer) + getSheetContainer().findFirstOfType( + RecordTypes.ProgTags.typeID + ); + if(progTags != null) { + RecordContainer progBinaryTag = (RecordContainer) + progTags.findFirstOfType( + RecordTypes.ProgBinaryTag.typeID + ); + if(progBinaryTag != null) { + CString binaryTag = (CString) + progBinaryTag.findFirstOfType( + RecordTypes.CString.typeID + ); + if(binaryTag != null) tag = binaryTag.getText(); + } + } + + return tag; + + } + + } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java index 48f2fdefcc..c524f31f70 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java @@ -440,14 +440,24 @@ public class Slide extends Sheet public HeadersFooters getHeadersFooters(){ HeadersFootersContainer hdd = null; Record[] ch = getSheetContainer().getChildRecords(); + boolean ppt2007 = false; for (int i = 0; i < ch.length; i++) { if(ch[i] instanceof HeadersFootersContainer){ hdd = (HeadersFootersContainer)ch[i]; - break; + } else if (ch[i].getRecordType() == RecordTypes.RoundTripContentMasterId.typeID){ + ppt2007 = true; } } boolean newRecord = false; - if(hdd == null) return getSlideShow().getSlideHeadersFooters(); - else return new HeadersFooters(hdd, getSlideShow(), newRecord); + if(hdd == null && !ppt2007) { + return getSlideShow().getSlideHeadersFooters(); + } + else { + if(hdd == null) { + hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer); + newRecord = true; + } + return new HeadersFooters(hdd, this, newRecord, ppt2007); + } } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java index 44cb2b2412..a9975ab370 100755 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java @@ -269,7 +269,7 @@ public abstract class TextShape extends SimpleShape { int type = getTextRun().getRunType(); MasterSheet master = getSheet().getMasterSheet(); if(master != null){ - TextShape masterShape = master.getPlaceholder(type); + TextShape masterShape = master.getPlaceholderByTextType(type); if(masterShape != null) valign = masterShape.getVerticalAlignment(); } else { //not found in the master sheet. Use the hardcoded defaults. diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java index 62a624af9d..9bfae4fccb 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java @@ -26,7 +26,7 @@ import java.io.OutputStream; /** * OEPlaceholderAtom (3011). *

- * Atom that describes the placeholder. + * An atom record that specifies whether a shape is a placeholder shape. *

* * @author Yegor Kozlov @@ -34,61 +34,169 @@ import java.io.OutputStream; public class OEPlaceholderAtom extends RecordAtom{ + /** + * The full size of the master body text placeholder shape. + */ public static final int PLACEHOLDER_FULLSIZE = 0; + + /** + * Half of the size of the master body text placeholder shape. + */ public static final int PLACEHOLDER_HALFSIZE = 1; + + /** + * A quarter of the size of the master body text placeholder shape. + */ public static final int PLACEHOLDER_QUARTSIZE = 2; + /** + * MUST NOT be used for this field. + */ public static final byte None = 0; + /** + * The corresponding shape contains the master title text. + * The corresponding slide MUST be a main master slide. + */ public static final byte MasterTitle = 1; + /** + * The corresponding shape contains the master body text. + * The corresponding slide MUST be a main master slide. + */ public static final byte MasterBody = 2; + /** + * The corresponding shape contains the master center title text. + * The corresponding slide MUST be a title master slide. + */ public static final byte MasterCenteredTitle = 3; - public static final byte MasterNotesSlideImage = 4; + /** + * The corresponding shape contains the master sub-title text. + * The corresponding slide MUST be a title master slide. + */ + public static final byte MasterSubTitle = 4; - public static final byte MasterNotesBodyImage = 5; + /** + * The corresponding shape contains the shared properties for slide image shapes. + * The corresponding slide MUST be a notes master slide. + */ + public static final byte MasterNotesSlideImage = 5; - public static final byte MasterDate = 6; + /** + * The corresponding shape contains the master body text. + * The corresponding slide MUST be a notes master slide. + */ + public static final byte MasterNotesBody = 6; - public static final byte MasterSlideNumber = 7; + /** + * The corresponding shape contains the date text field. + * The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide. + */ + public static final byte MasterDate = 7; - public static final byte MasterFooter = 8; + /** + * The corresponding shape contains a slide number text field. + * The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide. + */ + public static final byte MasterSlideNumber = 8; - public static final byte MasterHeader = 9; + /** + * The corresponding shape contains a footer text field. + * The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide. + */ + public static final byte MasterFooter = 9; - public static final byte MasterSubtitle = 10; + /** + * The corresponding shape contains a header text field. + * The corresponding slide must be a notes master slide or handout master slide. + */ + public static final byte MasterHeader = 10; - public static final byte GenericTextObject = 11; + /** + * The corresponding shape contains a presentation slide image. + * The corresponding slide MUST be a notes slide. + */ + public static final byte NotesSlideImage = 11; - public static final byte Title = 12; + /** + * The corresponding shape contains the notes text. + * The corresponding slide MUST be a notes slide. + */ + public static final byte NotesBody = 12; - public static final byte Body = 13; + /** + * The corresponding shape contains the title text. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Title = 13; - public static final byte NotesBody = 14; + /** + * The corresponding shape contains the body text. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Body = 14; + /** + * The corresponding shape contains the title text. + * The corresponding slide MUST be a presentation slide. + */ public static final byte CenteredTitle = 15; + /** + * The corresponding shape contains the sub-title text. + * The corresponding slide MUST be a presentation slide. + */ public static final byte Subtitle = 16; + /** + * The corresponding shape contains the title text with vertical text flow. + * The corresponding slide MUST be a presentation slide. + */ public static final byte VerticalTextTitle = 17; + /** + * The corresponding shape contains the body text with vertical text flow. + * The corresponding slide MUST be a presentation slide. + */ public static final byte VerticalTextBody = 18; - public static final byte NotesSlideImage = 19; + /** + * The corresponding shape contains a generic object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Object = 19; - public static final byte Object = 20; + /** + * The corresponding shape contains a chart object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Graph = 20; - public static final byte Graph = 21; + /** + * The corresponding shape contains a table object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Table = 21; - public static final byte Table = 22; + /** + * The corresponding shape contains a clipart object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte ClipArt = 22; - public static final byte ClipArt = 23; + /** + * The corresponding shape contains an organization chart object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte OrganizationChart = 23; - public static final byte OrganizationChart = 24; - - public static final byte MediaClip = 25; + /** + * The corresponding shape contains a media object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte MediaClip = 24; private byte[] _header; @@ -116,11 +224,13 @@ public class OEPlaceholderAtom extends RecordAtom{ */ protected OEPlaceholderAtom(byte[] source, int start, int len) { _header = new byte[8]; - System.arraycopy(source,start,_header,0,8); + int offset = start; + System.arraycopy(source,start,_header,0,8); + offset += _header.length; - placementId = LittleEndian.getInt(source, start); - placeholderId = LittleEndian.getUnsignedByte(source, start+4); - placeholderSize = LittleEndian.getUnsignedByte(source, start+5); + placementId = LittleEndian.getInt(source, offset); offset += 4; + placeholderId = LittleEndian.getUnsignedByte(source, offset); offset++; + placeholderSize = LittleEndian.getUnsignedByte(source, offset); offset++; } /** @@ -130,6 +240,11 @@ public class OEPlaceholderAtom extends RecordAtom{ /** * Returns the placement Id. + *

+ * The placement Id is a number assigned to the placeholder. It goes from -1 to the number of placeholders. + * It SHOULD be unique among all PlacholderAtom records contained in the corresponding slide. + * The value 0xFFFFFFFF specifies that the corresponding shape is not a placeholder shape. + *

* * @return the placement Id. */ @@ -139,6 +254,11 @@ public class OEPlaceholderAtom extends RecordAtom{ /** * Sets the placement Id. + *

+ * The placement Id is a number assigned to the placeholder. It goes from -1 to the number of placeholders. + * It SHOULD be unique among all PlacholderAtom records contained in the corresponding slide. + * The value 0xFFFFFFFF specifies that the corresponding shape is not a placeholder shape. + *

* * @param id the placement Id. */ @@ -149,6 +269,11 @@ public class OEPlaceholderAtom extends RecordAtom{ /** * Returns the placeholder Id. * + *

+ * placeholder Id specifies the type of the placeholder shape. + * The value MUST be one of the static constants defined in this class + *

+ * * @return the placeholder Id. */ public int getPlaceholderId(){ @@ -158,6 +283,10 @@ public class OEPlaceholderAtom extends RecordAtom{ /** * Sets the placeholder Id. * + *

+ * placeholder Id specifies the type of the placeholder shape. + * The value MUST be one of the static constants defined in this class + *

* @param id the placeholder Id. */ public void setPlaceholderId(byte id){ diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java index d7a664725e..9c867d5ab0 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java @@ -162,6 +162,17 @@ public class RecordTypes { // Records ~12050 seem to be related to Document Encryption public static final Type DocumentEncryptionAtom = new Type(12052,DocumentEncryptionAtom.class); + public static final Type OriginalMainMasterId = new Type(1052,null); + public static final Type CompositeMasterId = new Type(1052,null); + public static final Type RoundTripContentMasterInfo12 = new Type(1054,null); + public static final Type RoundTripShapeId12 = new Type(1055,null); + public static final Type RoundTripHFPlaceholder12 = new Type(1056,RoundTripHFPlaceholder12.class); + public static final Type RoundTripContentMasterId = new Type(1058,null); + public static final Type RoundTripOArtTextStyles12 = new Type(1059,null); + public static final Type RoundTripShapeCheckSumForCustomLayouts12 = new Type(1062,null); + public static final Type RoundTripNotesMasterTextStyles12 = new Type(1063,null); + public static final Type RoundTripCustomTableStyles12 = new Type(1064,null); + //records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher public static final int EscherDggContainer = 0xf000; public static final int EscherDgg = 0xf006; diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java b/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java new file mode 100644 index 0000000000..0f49b5bd03 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java @@ -0,0 +1,99 @@ +/* ==================================================================== + 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 java.util.Date; + +import org.apache.poi.hslf.util.SystemTimeUtils; +import org.apache.poi.util.LittleEndian; + +/** + * An atom record that specifies that a shape is a header or footer placeholder shape + * + * @since PowerPoint 2007 + * @author Yegor Kozlov + */ + +public class RoundTripHFPlaceholder12 extends RecordAtom +{ + /** + * Record header. + */ + private byte[] _header; + + /** + * Specifies the placeholder shape ID. + * + * MUST be {@link OEPlaceholderAtom#MasterDate}, {@link OEPlaceholderAtom#MasterSlideNumber}, + * {@link OEPlaceholderAtom#MasterFooter}, or {@link OEPlaceholderAtom#MasterHeader} + */ + private byte _placeholderId; + + /** + * Constructs the comment 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. + */ + protected RoundTripHFPlaceholder12(byte[] source, int start, int len) { + // Get the header. + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Get the record data. + _placeholderId = source[start+8]; + } + + /** + * Gets the comment number (note - each user normally has their own count). + * @return the comment number. + */ + public int getPlaceholderId() { + return _placeholderId; + } + + /** + * Sets the comment number (note - each user normally has their own count). + * @param number the comment number. + */ + public void setPlaceholderId(int number) { + _placeholderId = (byte)number; + } + + /** + * Gets the record type. + * @return the record type. + */ + public long getRecordType() { return RecordTypes.RoundTripHFPlaceholder12.typeID; } + + /** + * 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); + out.write(_placeholderId); + } +} \ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java index 1b2b9f5eeb..a546d0444c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java @@ -37,14 +37,7 @@ import org.apache.poi.ddf.EscherRecord; import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.model.HeadersFooters; -import org.apache.poi.hslf.model.Notes; -import org.apache.poi.hslf.model.PPFont; -import org.apache.poi.hslf.model.Picture; -import org.apache.poi.hslf.model.Shape; -import org.apache.poi.hslf.model.Slide; -import org.apache.poi.hslf.model.SlideMaster; -import org.apache.poi.hslf.model.TitleMaster; +import org.apache.poi.hslf.model.*; import org.apache.poi.hslf.record.Document; import org.apache.poi.hslf.record.DocumentAtom; import org.apache.poi.hslf.record.FontCollection; @@ -843,6 +836,10 @@ public final class SlideShow { * @return Header / Footer settings for slides */ public HeadersFooters getSlideHeadersFooters(){ + //detect if this ppt was saved in Office2007 + String tag = getSlidesMasters()[0].getProgrammableTag(); + boolean ppt2007 = "___PPT12".equals(tag); + HeadersFootersContainer hdd = null; Record[] ch = _documentRecord.getChildRecords(); for (int i = 0; i < ch.length; i++) { @@ -857,7 +854,7 @@ public final class SlideShow { hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer); newRecord = true; } - return new HeadersFooters(hdd, this, newRecord); + return new HeadersFooters(hdd, this, newRecord, ppt2007); } /** @@ -866,6 +863,10 @@ public final class SlideShow { * @return Header / Footer settings for notes */ public HeadersFooters getNotesHeadersFooters(){ + //detect if this ppt was saved in Office2007 + String tag = getSlidesMasters()[0].getProgrammableTag(); + boolean ppt2007 = "___PPT12".equals(tag); + HeadersFootersContainer hdd = null; Record[] ch = _documentRecord.getChildRecords(); for (int i = 0; i < ch.length; i++) { @@ -873,13 +874,18 @@ public final class SlideShow { ((HeadersFootersContainer)ch[i]).getOptions() == HeadersFootersContainer.NotesHeadersFootersContainer){ hdd = (HeadersFootersContainer)ch[i]; break; - } + } } boolean newRecord = false; if(hdd == null) { hdd = new HeadersFootersContainer(HeadersFootersContainer.NotesHeadersFootersContainer); newRecord = true; } - return new HeadersFooters(hdd, this, newRecord); + if(ppt2007 && _notes.length > 0){ + return new HeadersFooters(hdd, _notes[0], newRecord, ppt2007); + } else { + return new HeadersFooters(hdd, this, newRecord, ppt2007); + } } + } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/headers_footers_2007.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/headers_footers_2007.ppt new file mode 100644 index 0000000000000000000000000000000000000000..51b2c53b627757d172f3ce620ec3322e5960e90d GIT binary patch literal 169472 zcmeFabzD}<+CO~L%}uAIfRr>yNJ$7%N~1`(bayw>sf09wbV~>b2uOEJ36g>+UGG|` zd%M~DoU`BO`Qtsm_qT`7TGO*;u9>;6?_4u;GtiGcpHW7#0J&m>AaIcL3ls?AFX3>2 zTMFh!02Ty@zqkN>KWzyhP7-+T0uK=NkNH1<0#L{*+&6Rx1O~DOM-TL+Hvt4P5A-eg zfNlgJ3>A1_fd}mWAKecFh3vxV0UlOJCltsIVS@}o;eW(KA)`o1fExm-fr12zqCO&L-l*ALWM)rv3RX&<68>HaJp1 z8>}>F{~RqKIY7T31Z{^6uzg^F6v%#H5OQD(@P;(OU;(vih5>?*+b=^dV32`2!N3A} zkwqZnU%)zpxxf@)*a6TC3dj!h8kimO6%K3z_}yQOH|T~!29OMZOcW42`0r`);lZ?Z zv8DTv_s<19X$Y7=8~ii{1Q-4`mc{AW2S)L428N0a z3OR-|z6>~ryX;7y+#kj90xqz~pLU_YFejMO?S&492=IVKfu#L>ba7D#Fb)_9F2ovg z0tbeH#u{+^^n;~}0R2M&xwvdPKoWSc+kP65BEgaZf(!v(t*0-=Qm%LQh3C@$Df0G0kC0~iyA3l;>782HP|H3LrI5r$0um_t*S zoB#s?3sLxsFeuP(%0QN%{RWPk-}(-$!KL}$r{LK783*>!ck?|C9P2;hV1LB1UMU-_ z-_JCcgYdF|@A<(-|BSm@HaO;g#{DcC3ZaL83w-px3>+|q5HCB63Zhz!)C!D7NIp;l zpaWqaiCJ0N8(P|HE4x@5+C64*wlJs6gomY12dMFn`M;V1?oqw+t!!BS+fogF%S@qU zyp;aWzcu$`N6|w|d6U};ENhT8E@y)fbil^7(((kGh=CNKP3Gz~<{3kd8bKA?tdawr!ZinXbv!p7Q{UrI$cl@Mz@p#nzPLfW7T8 zcg!*ce#{r$)pxPdOyc1g*HzgBjMg4S8B!5$yl4H(u|9DY9$5&)R09u)%ItOZ%ng<7 zUCa&bK)Hb4BaP|HMkKP(7~*7d?r~G>0S(?;N+zdu7{)lNH4&36oTXXAqum(RUg3M0 ziRzmMTyPijFgSJGv)M?9k#2taB4akQHl~$2rKo5w)pI$wZ4_MWUg4>24CI<5TO(%K z+1&}YxSLTcn540~wP*BT#^N=4_M=0$;dmOKPh=sBv4|rfX)U)3d?_<4oAbJtgH5I2 zG+nvg*(i^VzRo{mWcCy(2Vw5_Nelyf6M%|;E%ty!e=vU`1n>yDBZUB{mL6Faz3lIuv4~T+KBc%Dh92f)f2L2$x`alSH11pLv z>w_Qb1RxIbFV_dmU?fllET9y3!1;ZZ0e5AU0ixFl;1Rim6Ceiq<0^v^2mwp+24EE~ z

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 XMB*>5Cb<8Z^#8?2es=l4`T743iXt^A literal 0 HcmV?d00001 diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java index 8b1cdbe09e..39255d3e8b 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java @@ -77,6 +77,112 @@ public class TestHeadersFooters extends TestCase assertEquals("custom date format", hd2.getDateTimeText()); } + /** + * If Headers / Footers are not set, all the getters should return false or null + */ + public void testReadNoHeadersFooters() throws Exception + { + File file = new File(cwd, "basic_test_ppt_file.ppt"); + FileInputStream is = new FileInputStream(file); + SlideShow ppt = new SlideShow(is); + is.close(); + + HeadersFooters slideHdd = ppt.getSlideHeadersFooters(); + assertFalse(slideHdd.isFooterVisible()); + assertNull(slideHdd.getFooterText()); + assertFalse(slideHdd.isSlideNumberVisible()); + assertFalse(slideHdd.isHeaderVisible()); + assertNull(slideHdd.getHeaderText()); + assertFalse(slideHdd.isUserDateVisible()); + assertNull(slideHdd.getDateTimeText()); + + + HeadersFooters notesHdd = ppt.getNotesHeadersFooters(); + assertFalse(notesHdd.isFooterVisible()); + assertNull(notesHdd.getFooterText()); + assertFalse(notesHdd.isHeaderVisible()); + assertNull(notesHdd.getHeaderText()); + assertFalse(notesHdd.isUserDateVisible()); + assertNull(notesHdd.getDateTimeText()); + + Slide[] slide = ppt.getSlides(); + for(int i=0 ; i < slide.length; i++){ + HeadersFooters hd1 = slide[i].getHeadersFooters(); + assertFalse(hd1.isFooterVisible()); + assertNull(hd1.getFooterText()); + assertFalse(hd1.isHeaderVisible()); + assertNull(hd1.getHeaderText()); + assertFalse(hd1.isUserDateVisible()); + assertNull(hd1.getDateTimeText()); + } + } + + /** + * Test extraction of headers / footers from PPTs saved in Office 2007 + */ + public void testRead2007() throws Exception + { + File file = new File(cwd, "headers_footers_2007.ppt"); + FileInputStream is = new FileInputStream(file); + SlideShow ppt = new SlideShow(is); + is.close(); + + HeadersFooters slideHdd = ppt.getSlideHeadersFooters(); + assertTrue(slideHdd.isFooterVisible()); + assertEquals("THE FOOTER TEXT", slideHdd.getFooterText()); + assertTrue(slideHdd.isSlideNumberVisible()); + assertFalse(slideHdd.isHeaderVisible()); + assertNull(slideHdd.getHeaderText()); + assertTrue(slideHdd.isUserDateVisible()); + assertEquals("Wednesday, August 06, 2008", slideHdd.getDateTimeText()); + + + HeadersFooters notesHdd = ppt.getNotesHeadersFooters(); + assertTrue(notesHdd.isFooterVisible()); + assertEquals("THE NOTES FOOTER TEXT", notesHdd.getFooterText()); + assertTrue(notesHdd.isHeaderVisible()); + assertEquals("THE NOTES HEADER TEXT", notesHdd.getHeaderText()); + assertTrue(notesHdd.isUserDateVisible()); + assertTrue(notesHdd.isDateTimeVisible()); + //TODO: depending on the formatId getDateTimeText() should return formatted date + //assertEquals("08/12/08", notesHdd.getDateTimeText()); + + //per-slide headers / footers + Slide[] slide = ppt.getSlides(); + //the first slide uses presentation-scope headers / footers + HeadersFooters hd1 = slide[0].getHeadersFooters(); + assertTrue(hd1.isFooterVisible()); + assertEquals("THE FOOTER TEXT", hd1.getFooterText()); + assertTrue(hd1.isSlideNumberVisible()); + assertFalse(hd1.isHeaderVisible()); + assertNull(hd1.getHeaderText()); + assertTrue(hd1.isUserDateVisible()); + assertTrue(hd1.isDateTimeVisible()); + assertEquals("Wednesday, August 06, 2008", hd1.getDateTimeText()); + + //the second slide uses custom per-slide headers / footers + HeadersFooters hd2 = slide[1].getHeadersFooters(); + assertTrue(hd2.isFooterVisible()); + assertEquals("THE FOOTER TEXT FOR SLIDE 2", hd2.getFooterText()); + assertTrue(hd2.isSlideNumberVisible()); + assertFalse(hd2.isHeaderVisible()); + assertNull(hd2.getHeaderText()); + assertTrue(hd2.isUserDateVisible()); + assertTrue(hd2.isDateTimeVisible()); + assertEquals("August 06, 2008", hd2.getDateTimeText()); + + //the third slide uses per-slide headers / footers + HeadersFooters hd3 = slide[2].getHeadersFooters(); + assertTrue(hd3.isFooterVisible()); + assertEquals("THE FOOTER TEXT", hd3.getFooterText()); + assertTrue(hd3.isSlideNumberVisible()); + assertFalse(hd3.isHeaderVisible()); + assertNull(hd3.getHeaderText()); + assertTrue(hd3.isUserDateVisible()); + assertTrue(hd3.isDateTimeVisible()); + assertEquals("Wednesday, August 06, 2008", hd3.getDateTimeText()); + } + public void testCreateSlideFooters() throws Exception { SlideShow ppt = new SlideShow();