Skip to content

Commit

Permalink
Handle OST 2013 files, which contain an additional field to indicate …
Browse files Browse the repository at this point in the history
…the expanded size of a block. Use new mechanism to select the appropriate set of data fields to read in, and also the size of the data field
  • Loading branch information
Jmcleodfoss committed Jul 22, 2020
1 parent 0322eea commit ab166ae
Showing 1 changed file with 37 additions and 26 deletions.
63 changes: 37 additions & 26 deletions pst/src/main/java/io/github/jmcleodfoss/pst/BBTEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,52 @@
* @see io.github.jmcleodfoss.pst.PagedBTree
* @see io.github.jmcleodfoss.pst.PagedBTree.BTEntry
* @see <a href="https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-pst/53a4b926-8ac4-45c9-9c6d-8358d951dbcd">MS-PST Section 2.2.2.7.7.3: BBTEntry (Leaf BBT Entry)</a>
* @see <a href="https://blog.mythicsoft.com/ost-2013-file-format-the-missing-documentation/">OST 2013 file format the missing documentation blog entry</a>
*/
class BBTEntry implements BTreeLeaf
{
private static final String nm_bref = "BREF";
private static final String nm_cb = "cb";
private static final String nm_cbInflated = "cbInflated";
private static final String nm_cRef = "cRef";

/** The Unicode-specific fields in the input stream which make up the block B-tree leaf entry. */
private static final DataDefinition[] unicode_fields = {
new DataDefinition(nm_bref, DataType.brefUnicodeReader, true),
};

/** The size in bytes of the Unicode-specific fields in a block B-tree leaf entry. */
private static final int UNICODE_SIZE = DataDefinition.size(unicode_fields);

/** The ANSI-specific fields in the input stream which make up the block B-tree leaf entry. */
private static final DataDefinition[] ansi_fields = {
new DataDefinition(nm_bref, DataType.brefAnsiReader, true),
};

/** The size in bytes of the Unicode-specific fields in a node B-tree leaf entry. */
private static final int ANSI_SIZE = DataDefinition.size(ansi_fields);

/** The fields common to both ANSI and Unicode files in the input stream which make up the block B-tree leaf entry. */
private static final DataDefinition[] common_fields = {
new DataDefinition(nm_cb, DataType.integer16Reader, true),
new DataDefinition(nm_cRef, DataType.integer16Reader, true)
/** The fields in the input stream which make up the block B-tree leaf entry, which are different depending on the file format type.
* @see <a href="https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-pst/53a4b926-8ac4-45c9-9c6d-8358d951dbcd">MS-PST Section 2.2.2.7.7.3: BBTEntry (Leaf BBT Entry)</a>
* @see <a href="https://blog.mythicsoft.com/ost-2013-file-format-the-missing-documentation/">OST 2013 file format the missing documentation blog entry</a>
*/
private static final DataDefinition fields[][] = {
/* ANSI fields and sizes */
{
new DataDefinition(nm_bref, DataType.brefAnsiReader, true),
new DataDefinition(nm_cb, DataType.integer16Reader, true),
new DataDefinition(nm_cRef, DataType.integer16Reader, true)
},

/* Unicode fields and sizes */
{
new DataDefinition(nm_bref, DataType.brefUnicodeReader, true),
new DataDefinition(nm_cb, DataType.integer16Reader, true),
new DataDefinition(nm_cRef, DataType.integer16Reader, true)
},

/* OST 2013 fields and sizes */
{
new DataDefinition(nm_bref, DataType.brefUnicodeReader, true),
new DataDefinition(nm_cb, DataType.integer16Reader, true),
new DataDefinition(nm_cbInflated, DataType.integer16Reader, true),
new DataDefinition(nm_cRef, DataType.integer16Reader, true)
}
};

/** The size in bytes of the fields common to ANSI and Unicode files in a block B-tree leaf entry. */
private static final int COMMON_SIZE = DataDefinition.size(common_fields);

/** The block reference for this block of the B-tree. */
final BREF bref;

/** The number of raw data bytes in the block. */
final int numBytes;

/** The total number of data bytes in the block accounting for compression. */
final int totalBytes;

/** The reference count of the block. */
private final int refCount;

Expand All @@ -58,9 +66,10 @@ class BBTEntry implements BTreeLeaf
java.io.IOException
{
DataContainer dc = new DataContainer();
dc.read(entryStream, context.unicode() ? unicode_fields : ansi_fields, common_fields);
dc.read(entryStream, fields[context.pstFile.header.fileFormat.index.getIndex()]);
bref = (BREF)dc.get(nm_bref);
numBytes = 0xffff & (Short)dc.get(nm_cb);
totalBytes = context.pstFile.header.fileFormat.index == FileFormat.Index.OST_2013 ? (0xffff & (Short)dc.get(nm_cbInflated)) : numBytes;
refCount = 0xffff & (Short)dc.get(nm_cRef);
}

Expand All @@ -70,7 +79,7 @@ class BBTEntry implements BTreeLeaf
*/
public int actualSize(final BTree.Context<BTree, BTreeLeaf> context)
{
return COMMON_SIZE + (context.unicode() ? UNICODE_SIZE : ANSI_SIZE);
return DataDefinition.size(fields[context.pstFile.header.fileFormat.index.getIndex()]);
}

/** {@inheritDoc} */
Expand Down Expand Up @@ -116,6 +125,8 @@ public java.nio.ByteBuffer rawData(final BlockMap bbt, final PSTFile pstFile)
@Override
public String toString()
{
return String.format(bref.toString() + " bytes %d ref count %d", numBytes, refCount);
if (numBytes == totalBytes)
return String.format(bref.toString() + " bytes %d ref count %d", numBytes, refCount);
return String.format(bref.toString() + " bytes %d (total %d) ref count %d", numBytes, totalBytes, refCount);
}
}

0 comments on commit ab166ae

Please sign in to comment.