View | Details | Raw Unified | Return to bug 38647
Collapse All | Expand All

(-)src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java (+121 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Copyright 2002-2004   Apache Software Foundation
3
4
   Licensed under the Apache License, Version 2.0 (the "License");
5
   you may not use this file except in compliance with the License.
6
   You may obtain a copy of the License at
7
8
       http://www.apache.org/licenses/LICENSE-2.0
9
10
   Unless required by applicable law or agreed to in writing, software
11
   distributed under the License is distributed on an "AS IS" BASIS,
12
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
   See the License for the specific language governing permissions and
14
   limitations under the License.
15
==================================================================== */
16
17
18
package org.apache.poi.hwpf.model;
19
20
import java.io.IOException;
21
import java.util.Arrays;
22
import java.util.Collections;
23
import java.util.List;
24
25
import org.apache.poi.util.LittleEndian;
26
import org.apache.poi.util.StringUtil;
27
28
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
29
30
/**
31
 * String table containing the history of the last few revisions ("saves") of the document.
32
 * Read-only for the time being.
33
 * 
34
 * @author Daniel Noll
35
 */
36
public class SavedByTable
37
{
38
  /**
39
   * A value that I don't know what it does, but is maintained for accuracy.
40
   */
41
  private short unknownValue = -1;
42
43
  /**
44
   * Array of entries.
45
   */
46
  private SavedByEntry[] entries;
47
48
  /**
49
   * Constructor to read the table from the table stream.
50
   *
51
   * @param tableStream the table stream.
52
   * @param offset the offset into the byte array.
53
   * @param size the size of the table in the byte array.
54
   */
55
  public SavedByTable(byte[] tableStream, int offset, int size)
56
  {
57
    // Read the value that I don't know what it does. :-)
58
    unknownValue = LittleEndian.getShort(tableStream, offset);
59
    offset += 2;
60
61
    // The stored int is the number of strings, and there are two strings per entry.
62
    int numEntries = LittleEndian.getInt(tableStream, offset) / 2;
63
    offset += 4;
64
65
    entries = new SavedByEntry[numEntries];
66
    for (int i = 0; i < numEntries; i++)
67
    {
68
      int len = LittleEndian.getShort(tableStream, offset);
69
      offset += 2;
70
      String userName = StringUtil.getFromUnicodeLE(tableStream, offset, len);
71
      offset += len * 2;
72
      len = LittleEndian.getShort(tableStream, offset);
73
      offset += 2;
74
      String saveLocation = StringUtil.getFromUnicodeLE(tableStream, offset, len);
75
      offset += len * 2;
76
77
      entries[i] = new SavedByEntry(userName, saveLocation);
78
    }
79
  }
80
81
  /**
82
   * Gets the entries.  The returned list cannot be modified.
83
   *
84
   * @return the list of entries.
85
   */
86
  public List getEntries()
87
  {
88
    return Collections.unmodifiableList(Arrays.asList(entries));
89
  }
90
91
  /**
92
   * Writes this table to the table stream.
93
   *
94
   * @param tableStream the table stream to write to.
95
   * @throws IOException if an error occurs while writing.
96
   */
97
  public void writeTo(HWPFOutputStream tableStream)
98
    throws IOException
99
  {
100
    byte[] header = new byte[6];
101
    LittleEndian.putShort(header, 0, unknownValue);
102
    LittleEndian.putInt(header, 2, entries.length * 2);
103
    tableStream.write(header);
104
105
    for (int i = 0; i < entries.length; i++)
106
    {
107
      writeStringValue(tableStream, entries[i].getUserName());
108
      writeStringValue(tableStream, entries[i].getSaveLocation());
109
    }
110
  }
111
112
  private void writeStringValue(HWPFOutputStream tableStream, String value)
113
    throws IOException
114
  {
115
    byte[] buf = new byte[value.length() * 2 + 2];
116
    LittleEndian.putShort(buf, 0, (short) value.length());
117
    StringUtil.putUnicodeLE(value, buf, 2);
118
    tableStream.write(buf);
119
  }
120
}
121
0
  + *
122
  + *
(-)src/scratchpad/src/org/apache/poi/hwpf/model/SavedByEntry.java (+85 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Copyright 2002-2004   Apache Software Foundation
3
4
   Licensed under the Apache License, Version 2.0 (the "License");
5
   you may not use this file except in compliance with the License.
6
   You may obtain a copy of the License at
7
8
       http://www.apache.org/licenses/LICENSE-2.0
9
10
   Unless required by applicable law or agreed to in writing, software
11
   distributed under the License is distributed on an "AS IS" BASIS,
12
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
   See the License for the specific language governing permissions and
14
   limitations under the License.
15
==================================================================== */
16
17
18
package org.apache.poi.hwpf.model;
19
20
21
/**
22
 * A single entry in the {@link SavedByTable}.
23
 * 
24
 * @author Daniel Noll
25
 */
26
public class SavedByEntry
27
{
28
  private String userName;
29
  private String saveLocation;
30
31
  public SavedByEntry(String userName, String saveLocation)
32
  {
33
    this.userName = userName;
34
    this.saveLocation = saveLocation;
35
  }
36
37
  public String getUserName()
38
  {
39
    return userName;
40
  }
41
42
  public String getSaveLocation()
43
  {
44
    return saveLocation;
45
  }
46
47
  /**
48
   * Compares this object with another, for equality.
49
   *
50
   * @param other the object to compare to this one.
51
   * @return <code>true</code> iff the other object is equal to this one.
52
   */
53
  public boolean equals(Object other)
54
  {
55
    if (other == this) return true;
56
    if (!(other instanceof SavedByEntry)) return false;
57
    SavedByEntry that = (SavedByEntry) other;
58
    return that.userName.equals(userName) &&
59
           that.saveLocation.equals(saveLocation);
60
  }
61
62
  /**
63
   * Generates a hash code for consistency with {@link #equals(Object)}.
64
   *
65
   * @return the hash code.
66
   */
67
  public int hashCode()
68
  {
69
    int hash = 29;
70
    hash = hash * 13 + userName.hashCode();
71
    hash = hash * 13 + saveLocation.hashCode();
72
    return hash;
73
  }
74
75
  /**
76
   * Returns a string for display.
77
   *
78
   * @return the string.
79
   */
80
  public String toString()
81
  {
82
    return "SavedByEntry[userName=" + getUserName() +
83
                       ",saveLocation=" + getSaveLocation() + "]";
84
  }
85
}
0
  + *
86
  + *
(-)src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java (+21 lines)
Lines 61-66 Link Here
61
      fieldSet.add(new Integer(FIBFieldHandler.PLFLFO));
61
      fieldSet.add(new Integer(FIBFieldHandler.PLFLFO));
62
      fieldSet.add(new Integer(FIBFieldHandler.PLCFFLDMOM));
62
      fieldSet.add(new Integer(FIBFieldHandler.PLCFFLDMOM));
63
      fieldSet.add(new Integer(FIBFieldHandler.STTBFFFN));
63
      fieldSet.add(new Integer(FIBFieldHandler.STTBFFFN));
64
      fieldSet.add(new Integer(FIBFieldHandler.STTBSAVEDBY));
64
      fieldSet.add(new Integer(FIBFieldHandler.MODIFIED));
65
      fieldSet.add(new Integer(FIBFieldHandler.MODIFIED));
65
66
66
67
Lines 251-256 Link Here
251
      _fieldHandler.setFieldSize(FIBFieldHandler.STTBFFFN, lcbSttbFffn);
252
      _fieldHandler.setFieldSize(FIBFieldHandler.STTBFFFN, lcbSttbFffn);
252
    }
253
    }
253
254
255
    public int getFcSttbSavedBy()
256
    {
257
        return _fieldHandler.getFieldOffset(FIBFieldHandler.STTBSAVEDBY);
258
    }
259
260
    public int getLcbSttbSavedBy()
261
    {
262
        return _fieldHandler.getFieldSize(FIBFieldHandler.STTBSAVEDBY);
263
    }
264
265
    public void setFcSttbSavedBy(int fcSttbSavedBy)
266
    {
267
      _fieldHandler.setFieldOffset(FIBFieldHandler.STTBSAVEDBY, fcSttbSavedBy);
268
    }
269
270
    public void setLcbSttbSavedBy(int fcSttbSavedBy)
271
    {
272
      _fieldHandler.setFieldSize(FIBFieldHandler.STTBSAVEDBY, fcSttbSavedBy);
273
    }
274
254
    public int getModifiedLow()
275
    public int getModifiedLow()
255
    {
276
    {
256
      return _fieldHandler.getFieldOffset(FIBFieldHandler.PLFLFO);
277
      return _fieldHandler.getFieldOffset(FIBFieldHandler.PLFLFO);
(-)src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (+31 lines)
Lines 86-91 Link Here
86
  /** Hold list tables */
86
  /** Hold list tables */
87
  protected ListTables _lt;
87
  protected ListTables _lt;
88
88
89
  /** Holds the save history for this document. */
90
  protected SavedByTable _sbt;
91
89
  protected HWPFDocument()
92
  protected HWPFDocument()
90
  {
93
  {
91
94
Lines 212-217 Link Here
212
      _lt = new ListTables(_tableStream, _fib.getFcPlcfLst(), _fib.getFcPlfLfo());
215
      _lt = new ListTables(_tableStream, _fib.getFcPlcfLst(), _fib.getFcPlfLfo());
213
    }
216
    }
214
217
218
    int sbtOffset = _fib.getFcSttbSavedBy();
219
    int sbtLength = _fib.getLcbSttbSavedBy();
220
    if (sbtOffset != 0 && sbtLength != 0)
221
    {
222
      _sbt = new SavedByTable(_tableStream, sbtOffset, sbtLength);
223
    }
224
215
    PlexOfCps plc = new PlexOfCps(_tableStream, _fib.getFcPlcffldMom(), _fib.getLcbPlcffldMom(), 2);
225
    PlexOfCps plc = new PlexOfCps(_tableStream, _fib.getFcPlcffldMom(), _fib.getLcbPlcffldMom(), 2);
216
    for (int x = 0; x < plc.length(); x++)
226
    for (int x = 0; x < plc.length(); x++)
217
    {
227
    {
Lines 267-273 Link Here
267
  {
277
  {
268
    return _lt;
278
    return _lt;
269
  }
279
  }
280
270
  /**
281
  /**
282
   * Gets a reference to the saved -by table, which holds the save history for the document.
283
   *
284
   * @return the saved-by table.
285
   */
286
  public SavedByTable getSavedByTable()
287
  {
288
    return _sbt;
289
  }
290
291
  /**
271
   * Writes out the word file that is represented by an instance of this class.
292
   * Writes out the word file that is represented by an instance of this class.
272
   *
293
   *
273
   * @param out The OutputStream to write to.
294
   * @param out The OutputStream to write to.
Lines 347-352 Link Here
347
      tableOffset = tableStream.getOffset();
368
      tableOffset = tableStream.getOffset();
348
    }
369
    }
349
370
371
    // write out the saved-by table.
372
    if (_sbt != null)
373
    {
374
      _fib.setFcSttbSavedBy(tableOffset);
375
      _sbt.writeTo(tableStream);
376
      _fib.setLcbSttbSavedBy(tableStream.getOffset() - tableOffset);
377
378
      tableOffset = tableStream.getOffset();
379
    }
380
350
    // write out the FontTable.
381
    // write out the FontTable.
351
    _fib.setFcSttbfffn(tableOffset);
382
    _fib.setFcSttbfffn(tableOffset);
352
    _ft.writeTo(docSys);
383
    _ft.writeTo(docSys);
(-)src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSavedByTable.java (+91 lines)
Line 0 Link Here
1
2
/* ====================================================================
3
   Copyright 2002-2004   Apache Software Foundation
4
5
   Licensed under the Apache License, Version 2.0 (the "License");
6
   you may not use this file except in compliance with the License.
7
   You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
19
package org.apache.poi.hwpf.model;
20
21
import java.io.*;
22
import java.util.*;
23
import junit.framework.*;
24
25
import org.apache.poi.hwpf.*;
26
import org.apache.poi.hwpf.model.*;
27
import org.apache.poi.util.*;
28
29
/**
30
 * Unit test for {@link SavedByTable} and {@link SavedByEntry}.
31
 *
32
 * @author Daniel Noll
33
 */
34
public class TestSavedByTable
35
  extends TestCase
36
{
37
  /** Data dir */
38
  private File testFile = new File(new File(System.getProperty("HWPF.testdata.path")), "saved-by-table.doc");
39
40
  /** The expected entries in the test document. */
41
  private List expected = Arrays.asList(new Object[] {
42
    new SavedByEntry("cic22", "C:\\DOCUME~1\\phamill\\LOCALS~1\\Temp\\AutoRecovery save of Iraq - security.asd"),
43
    new SavedByEntry("cic22", "C:\\DOCUME~1\\phamill\\LOCALS~1\\Temp\\AutoRecovery save of Iraq - security.asd"),
44
    new SavedByEntry("cic22", "C:\\DOCUME~1\\phamill\\LOCALS~1\\Temp\\AutoRecovery save of Iraq - security.asd"),
45
    new SavedByEntry("JPratt", "C:\\TEMP\\Iraq - security.doc"),
46
    new SavedByEntry("JPratt", "A:\\Iraq - security.doc"),
47
    new SavedByEntry("ablackshaw", "C:\\ABlackshaw\\Iraq - security.doc"),
48
    new SavedByEntry("ablackshaw", "C:\\ABlackshaw\\A;Iraq - security.doc"),
49
    new SavedByEntry("ablackshaw", "A:\\Iraq - security.doc"),
50
    new SavedByEntry("MKhan", "C:\\TEMP\\Iraq - security.doc"),
51
    new SavedByEntry("MKhan", "C:\\WINNT\\Profiles\\mkhan\\Desktop\\Iraq.doc")
52
  });
53
54
  /**
55
   * Tests reading in the entries, comparing them against the expected entries.
56
   * Then tests writing the document out and reading the entries yet again.
57
   *
58
   * @throws Exception if an unexpected error occurs.
59
   */
60
  public void testReadWrite()
61
    throws Exception
62
  {
63
    // This document is widely available on the internet as "blair.doc".
64
    // I tried stripping the content and saving the document but my version
65
    // of Word (from Office XP) strips this table out.
66
    InputStream stream = new BufferedInputStream(new FileInputStream(testFile));
67
    HWPFDocument doc;
68
    try
69
    {
70
      doc = new HWPFDocument(stream);
71
    }
72
    finally
73
    {
74
      stream.close();
75
    }
76
77
    // Check what we just read.
78
    assertEquals("List of saved-by entries was not as expected",
79
                 expected, doc.getSavedByTable().getEntries());
80
81
    // Now write the entire document out, and read it back in...
82
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
83
    doc.write(byteStream);
84
    InputStream copyStream = new ByteArrayInputStream(byteStream.toByteArray());
85
    HWPFDocument copy = new HWPFDocument(copyStream);
86
87
    // And check again.
88
    assertEquals("List of saved-by entries was incorrect after writing",
89
                 expected, copy.getSavedByTable().getEntries());
90
  }
91
}
0
  + *
92
  + *

Return to bug 38647