Author: nick Date: Mon Aug 14 03:29:49 2006 New Revision: 431320 URL: http://svn.apache.org/viewvc?rev=431320&view=rev Log: Access to Saved By Information - patch from Trejkaz in bug #38647
Added: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/data/saved-by-table.doc (with props) jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java?rev=431320&r1=431319&r2=431320&view=diff ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java Mon Aug 14 03:29:49 2006 @@ -86,6 +86,9 @@ /** Hold list tables */ protected ListTables _lt; + /** Holds the save history for this document. */ + protected SavedByTable _sbt; + protected HWPFDocument() { @@ -212,6 +215,13 @@ _lt = new ListTables(_tableStream, _fib.getFcPlcfLst(), _fib.getFcPlfLfo()); } + int sbtOffset = _fib.getFcSttbSavedBy(); + int sbtLength = _fib.getLcbSttbSavedBy(); + if (sbtOffset != 0 && sbtLength != 0) + { + _sbt = new SavedByTable(_tableStream, sbtOffset, sbtLength); + } + PlexOfCps plc = new PlexOfCps(_tableStream, _fib.getFcPlcffldMom(), _fib.getLcbPlcffldMom(), 2); for (int x = 0; x < plc.length(); x++) { @@ -267,6 +277,17 @@ { 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. * @@ -344,6 +365,16 @@ _fib.setFcPlfLfo(tableStream.getOffset()); _lt.writeListOverridesTo(tableStream); _fib.setLcbPlfLfo(tableStream.getOffset() - tableOffset); + 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(); } Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java?rev=431320&r1=431319&r2=431320&view=diff ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java Mon Aug 14 03:29:49 2006 @@ -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)); @@ -249,6 +250,26 @@ public void setLcbSttbfffn(int lcbSttbFffn) { _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() Added: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java?rev=431320&view=auto ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java (added) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java Mon Aug 14 03:29:49 2006 @@ -0,0 +1,85 @@ +/* ==================================================================== + 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 [EMAIL PROTECTED] 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; + } + + /** + * Compares this object with another, for equality. + * + * @param other the object to compare to this one. + * @return <code>true</code> iff the other object is equal to this one. + */ + public boolean equals(Object other) + { + if (other == this) return true; + if (!(other instanceof SavedByEntry)) return false; + SavedByEntry that = (SavedByEntry) other; + return that.userName.equals(userName) && + that.saveLocation.equals(saveLocation); + } + + /** + * Generates a hash code for consistency with [EMAIL PROTECTED] #equals(Object)}. + * + * @return the hash code. + */ + public int hashCode() + { + int hash = 29; + hash = hash * 13 + userName.hashCode(); + hash = hash * 13 + saveLocation.hashCode(); + return hash; + } + + /** + * Returns a string for display. + * + * @return the string. + */ + public String toString() + { + return "SavedByEntry[userName=" + getUserName() + + ",saveLocation=" + getSaveLocation() + "]"; + } +} Added: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java?rev=431320&view=auto ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java (added) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java Mon Aug 14 03:29:49 2006 @@ -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); + } +} + Added: jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/data/saved-by-table.doc URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/data/saved-by-table.doc?rev=431320&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/data/saved-by-table.doc ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java?rev=431320&view=auto ============================================================================== --- jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java (added) +++ jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java Mon Aug 14 03:29:49 2006 @@ -0,0 +1,91 @@ + +/* ==================================================================== + 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.*; +import java.util.*; +import junit.framework.*; + +import org.apache.poi.hwpf.*; +import org.apache.poi.hwpf.model.*; +import org.apache.poi.util.*; + +/** + * Unit test for [EMAIL PROTECTED] SavedByTable} and [EMAIL PROTECTED] SavedByEntry}. + * + * @author Daniel Noll + */ +public class TestSavedByTable + extends TestCase +{ + /** Data dir */ + private File testFile = new File(new File(System.getProperty("HWPF.testdata.path")), "saved-by-table.doc"); + + /** The expected entries in the test document. */ + private List expected = Arrays.asList(new Object[] { + new SavedByEntry("cic22", "C:\\DOCUME~1\\phamill\\LOCALS~1\\Temp\\AutoRecovery save of Iraq - security.asd"), + new SavedByEntry("cic22", "C:\\DOCUME~1\\phamill\\LOCALS~1\\Temp\\AutoRecovery save of Iraq - security.asd"), + new SavedByEntry("cic22", "C:\\DOCUME~1\\phamill\\LOCALS~1\\Temp\\AutoRecovery save of Iraq - security.asd"), + new SavedByEntry("JPratt", "C:\\TEMP\\Iraq - security.doc"), + new SavedByEntry("JPratt", "A:\\Iraq - security.doc"), + new SavedByEntry("ablackshaw", "C:\\ABlackshaw\\Iraq - security.doc"), + new SavedByEntry("ablackshaw", "C:\\ABlackshaw\\A;Iraq - security.doc"), + new SavedByEntry("ablackshaw", "A:\\Iraq - security.doc"), + new SavedByEntry("MKhan", "C:\\TEMP\\Iraq - security.doc"), + new SavedByEntry("MKhan", "C:\\WINNT\\Profiles\\mkhan\\Desktop\\Iraq.doc") + }); + + /** + * Tests reading in the entries, comparing them against the expected entries. + * Then tests writing the document out and reading the entries yet again. + * + * @throws Exception if an unexpected error occurs. + */ + public void testReadWrite() + throws Exception + { + // This document is widely available on the internet as "blair.doc". + // I tried stripping the content and saving the document but my version + // of Word (from Office XP) strips this table out. + InputStream stream = new BufferedInputStream(new FileInputStream(testFile)); + HWPFDocument doc; + try + { + doc = new HWPFDocument(stream); + } + finally + { + stream.close(); + } + + // Check what we just read. + assertEquals("List of saved-by entries was not as expected", + expected, doc.getSavedByTable().getEntries()); + + // Now write the entire document out, and read it back in... + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + doc.write(byteStream); + InputStream copyStream = new ByteArrayInputStream(byteStream.toByteArray()); + HWPFDocument copy = new HWPFDocument(copyStream); + + // And check again. + assertEquals("List of saved-by entries was incorrect after writing", + expected, copy.getSavedByTable().getEntries()); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] Mailing List: http://jakarta.apache.org/site/mail2.html#poi The Apache Jakarta POI Project: http://jakarta.apache.org/poi/