ASF Bugzilla – Attachment 18712 Details for
Bug 38647
[PATCH][RFE] Access to "saved by" information in Word documents
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Updated patch, added test case and a little more API
saved-by-table.patch (text/plain), 14.85 KB, created by
Trejkaz (pen name)
on 2006-08-14 02:47:14 UTC
(
hide
)
Description:
Updated patch, added test case and a little more API
Filename:
MIME Type:
Creator:
Trejkaz (pen name)
Created:
2006-08-14 02:47:14 UTC
Size:
14.85 KB
patch
obsolete
>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,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 {@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; >+ } >+ >+ /** >+ * 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 {@link #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() + "]"; >+ } >+} > >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 431273) >+++ 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 431273) >+++ src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (working copy) >@@ -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,7 +277,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. >@@ -347,6 +368,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); >Index: src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java >=================================================================== >--- src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java (revision 0) >+++ src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java (revision 0) >@@ -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 {@link SavedByTable} and {@link 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()); >+ } >+} > >Property changes on: src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java >___________________________________________________________________ >Name: svn:executable > + * > >Index: src/scratchpad/testcases/org/apache/poi/hwpf/data/saved-by-table.doc >=================================================================== >Cannot display: file marked as a binary type. >svn:mime-type = application/octet-stream > >Property changes on: src/scratchpad/testcases/org/apache/poi/hwpf/data/saved-by-table.doc >___________________________________________________________________ >Name: svn:executable > + * >Name: svn:mime-type > + application/octet-stream >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 38647
:
17698
|
18510
|
18711
| 18712