Index: src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java =================================================================== --- src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java (revision 0) +++ src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java (revision 0) @@ -0,0 +1,121 @@ +/* ==================================================================== + Copyright 2002-2004 Apache Software Foundation + + Licensed 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.hwpf.model; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +import org.apache.poi.hwpf.model.io.HWPFOutputStream; + +/** + * String table containing the history of the last few revisions ("saves") of the document. + * Read-only for the time being. + * + * @author Daniel Noll + */ +public class SavedByTable +{ + /** + * A value that I don't know what it does, but is maintained for accuracy. + */ + private short unknownValue = -1; + + /** + * Array of entries. + */ + private SavedByEntry[] 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. + */ + public SavedByTable(byte[] tableStream, int offset, int size) + { + // Read the value that I don't know what it does. :-) + unknownValue = LittleEndian.getShort(tableStream, offset); + offset += 2; + + // The stored int is the number of strings, and there are two strings per entry. + int numEntries = LittleEndian.getInt(tableStream, offset) / 2; + offset += 4; + + entries = new SavedByEntry[numEntries]; + for (int i = 0; i < numEntries; i++) + { + int len = LittleEndian.getShort(tableStream, offset); + offset += 2; + String userName = StringUtil.getFromUnicodeLE(tableStream, offset, len); + offset += len * 2; + len = LittleEndian.getShort(tableStream, offset); + offset += 2; + String saveLocation = StringUtil.getFromUnicodeLE(tableStream, offset, len); + offset += len * 2; + + entries[i] = new SavedByEntry(userName, saveLocation); + } + } + + /** + * Gets the entries. The returned list cannot be modified. + * + * @return the list of entries. + */ + public List getEntries() + { + return Collections.unmodifiableList(Arrays.asList(entries)); + } + + /** + * 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(HWPFOutputStream tableStream) + throws IOException + { + byte[] header = new byte[6]; + LittleEndian.putShort(header, 0, unknownValue); + LittleEndian.putInt(header, 2, entries.length * 2); + tableStream.write(header); + + for (int i = 0; i < entries.length; i++) + { + writeStringValue(tableStream, entries[i].getUserName()); + writeStringValue(tableStream, entries[i].getSaveLocation()); + } + } + + private void writeStringValue(HWPFOutputStream tableStream, String value) + throws IOException + { + byte[] buf = new byte[value.length() * 2 + 2]; + LittleEndian.putShort(buf, 0, (short) value.length()); + StringUtil.putUnicodeLE(value, buf, 2); + tableStream.write(buf); + } +} + Property changes on: src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java ___________________________________________________________________ Name: svn:executable + * Index: src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java =================================================================== --- src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java (revision 0) +++ src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java (revision 0) @@ -0,0 +1,46 @@ +/* ==================================================================== + Copyright 2002-2004 Apache Software Foundation + + Licensed 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.hwpf.model; + + +/** + * A single entry in the {@link SavedByTable}. + * + * @author Daniel Noll + */ +public class SavedByEntry +{ + private String userName; + private String saveLocation; + + public SavedByEntry(String userName, String saveLocation) + { + this.userName = userName; + this.saveLocation = saveLocation; + } + + public String getUserName() + { + return userName; + } + + public String getSaveLocation() + { + return saveLocation; + } +} Property changes on: src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java ___________________________________________________________________ Name: svn:executable + * Index: src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java =================================================================== --- src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java (revision 377867) +++ src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java (working copy) @@ -61,6 +61,7 @@ fieldSet.add(new Integer(FIBFieldHandler.PLFLFO)); fieldSet.add(new Integer(FIBFieldHandler.PLCFFLDMOM)); fieldSet.add(new Integer(FIBFieldHandler.STTBFFFN)); + fieldSet.add(new Integer(FIBFieldHandler.STTBSAVEDBY)); fieldSet.add(new Integer(FIBFieldHandler.MODIFIED)); @@ -251,6 +252,26 @@ _fieldHandler.setFieldSize(FIBFieldHandler.STTBFFFN, lcbSttbFffn); } + public int getFcSttbSavedBy() + { + return _fieldHandler.getFieldOffset(FIBFieldHandler.STTBSAVEDBY); + } + + public int getLcbSttbSavedBy() + { + return _fieldHandler.getFieldSize(FIBFieldHandler.STTBSAVEDBY); + } + + public void setFcSttbSavedBy(int fcSttbSavedBy) + { + _fieldHandler.setFieldOffset(FIBFieldHandler.STTBSAVEDBY, fcSttbSavedBy); + } + + public void setLcbSttbSavedBy(int fcSttbSavedBy) + { + _fieldHandler.setFieldSize(FIBFieldHandler.STTBSAVEDBY, fcSttbSavedBy); + } + public int getModifiedLow() { return _fieldHandler.getFieldOffset(FIBFieldHandler.PLFLFO); Index: src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java =================================================================== --- src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (revision 377867) +++ src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (working copy) @@ -89,6 +89,9 @@ /** Hold list tables */ protected ListTables _lt; + /** Holds the save history for this document. */ + protected SavedByTable _sbt; + protected HWPFDocument() { @@ -182,6 +185,12 @@ _lt = new ListTables(_tableStream, _fib.getFcPlcfLst(), _fib.getFcPlfLfo()); } + int sbtOffset = _fib.getFcSttbSavedBy(); + if (sbtOffset != 0) + { + _sbt = new SavedByTable(_tableStream, sbtOffset, _fib.getLcbSttbSavedBy()); + } + PlexOfCps plc = new PlexOfCps(_tableStream, _fib.getFcPlcffldMom(), _fib.getLcbPlcffldMom(), 2); for (int x = 0; x < plc.length(); x++) { @@ -237,7 +246,18 @@ { return _lt; } + /** + * Gets a reference to the saved -by table, which holds the save history for the document. + * + * @return the saved-by table. + */ + public SavedByTable getSavedByTable() + { + return _sbt; + } + + /** * Writes out the word file that is represented by an instance of this class. * * @param out The OutputStream to write to. @@ -317,6 +337,16 @@ tableOffset = tableStream.getOffset(); } + // write out the saved-by table. + if (_sbt != null) + { + _fib.setFcSttbSavedBy(tableOffset); + _sbt.writeTo(tableStream); + _fib.setLcbSttbSavedBy(tableStream.getOffset() - tableOffset); + + tableOffset = tableStream.getOffset(); + } + // write out the FontTable. _fib.setFcSttbfffn(tableOffset); _ft.writeTo(docSys);