You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@poi.apache.org by ni...@apache.org on 2006/08/14 12:29:50 UTC

svn commit: r431320 - in /jakarta/poi/trunk/src/scratchpad: src/org/apache/poi/hwpf/ src/org/apache/poi/hwpf/model/ testcases/org/apache/poi/hwpf/data/ testcases/org/apache/poi/hwpf/model/

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 {@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() + "]";
+  }
+}

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 {@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());
+  }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: poi-dev-unsubscribe@jakarta.apache.org
Mailing List:    http://jakarta.apache.org/site/mail2.html#poi
The Apache Jakarta POI Project: http://jakarta.apache.org/poi/