diff --git a/pst/src/main/java/io/github/jmcleodfoss/pst/BBTEntry.java b/pst/src/main/java/io/github/jmcleodfoss/pst/BBTEntry.java index d2a78175..2eebdac3 100644 --- a/pst/src/main/java/io/github/jmcleodfoss/pst/BBTEntry.java +++ b/pst/src/main/java/io/github/jmcleodfoss/pst/BBTEntry.java @@ -7,44 +7,52 @@ * @see io.github.jmcleodfoss.pst.PagedBTree * @see io.github.jmcleodfoss.pst.PagedBTree.BTEntry * @see MS-PST Section 2.2.2.7.7.3: BBTEntry (Leaf BBT Entry) +* @see OST 2013 file format the missing documentation blog entry */ 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 MS-PST Section 2.2.2.7.7.3: BBTEntry (Leaf BBT Entry) + * @see OST 2013 file format the missing documentation blog entry + */ + 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; @@ -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); } @@ -70,7 +79,7 @@ class BBTEntry implements BTreeLeaf */ public int actualSize(final BTree.Context context) { - return COMMON_SIZE + (context.unicode() ? UNICODE_SIZE : ANSI_SIZE); + return DataDefinition.size(fields[context.pstFile.header.fileFormat.index.getIndex()]); } /** {@inheritDoc} */ @@ -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); } }