mirror of https://github.com/apache/poi.git
Start to merge the POIFS classes HeaderBlockReader and HeaderBlockWriter into a common HeaderBlock class
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1050764 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4b8e5f61c1
commit
6703ad1c93
|
@ -18,21 +18,16 @@
|
||||||
package org.apache.poi.poifs.dev;
|
package org.apache.poi.poifs.dev;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.apache.poi.poifs.common.POIFSBigBlockSize;
|
import org.apache.poi.poifs.common.POIFSBigBlockSize;
|
||||||
import org.apache.poi.poifs.common.POIFSConstants;
|
import org.apache.poi.poifs.common.POIFSConstants;
|
||||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
|
||||||
import org.apache.poi.poifs.filesystem.DocumentNode;
|
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
|
||||||
import org.apache.poi.poifs.property.PropertyTable;
|
import org.apache.poi.poifs.property.PropertyTable;
|
||||||
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
||||||
import org.apache.poi.poifs.storage.BlockList;
|
import org.apache.poi.poifs.storage.BlockList;
|
||||||
import org.apache.poi.poifs.storage.HeaderBlockReader;
|
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||||
import org.apache.poi.poifs.storage.ListManagedBlock;
|
import org.apache.poi.poifs.storage.ListManagedBlock;
|
||||||
import org.apache.poi.poifs.storage.RawDataBlockList;
|
import org.apache.poi.poifs.storage.RawDataBlockList;
|
||||||
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
||||||
|
@ -67,51 +62,50 @@ public class POIFSHeaderDumper {
|
||||||
InputStream inp = new FileInputStream(filename);
|
InputStream inp = new FileInputStream(filename);
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
HeaderBlockReader header_block_reader =
|
HeaderBlock header_block = new HeaderBlock(inp);
|
||||||
new HeaderBlockReader(inp);
|
displayHeader(header_block);
|
||||||
displayHeader(header_block_reader);
|
|
||||||
|
|
||||||
// Raw blocks
|
// Raw blocks
|
||||||
POIFSBigBlockSize bigBlockSize = header_block_reader.getBigBlockSize();
|
POIFSBigBlockSize bigBlockSize = header_block.getBigBlockSize();
|
||||||
RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
|
RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
|
||||||
displayRawBlocksSummary(data_blocks);
|
displayRawBlocksSummary(data_blocks);
|
||||||
|
|
||||||
// Main FAT Table
|
// Main FAT Table
|
||||||
BlockAllocationTableReader batReader =
|
BlockAllocationTableReader batReader =
|
||||||
new BlockAllocationTableReader(
|
new BlockAllocationTableReader(
|
||||||
header_block_reader.getBigBlockSize(),
|
header_block.getBigBlockSize(),
|
||||||
header_block_reader.getBATCount(),
|
header_block.getBATCount(),
|
||||||
header_block_reader.getBATArray(),
|
header_block.getBATArray(),
|
||||||
header_block_reader.getXBATCount(),
|
header_block.getXBATCount(),
|
||||||
header_block_reader.getXBATIndex(),
|
header_block.getXBATIndex(),
|
||||||
data_blocks);
|
data_blocks);
|
||||||
displayBATReader(batReader);
|
displayBATReader(batReader);
|
||||||
|
|
||||||
// Properties Table
|
// Properties Table
|
||||||
PropertyTable properties =
|
PropertyTable properties =
|
||||||
new PropertyTable(
|
new PropertyTable(
|
||||||
header_block_reader.getBigBlockSize(),
|
header_block.getBigBlockSize(),
|
||||||
header_block_reader.getPropertyStart(),
|
header_block.getPropertyStart(),
|
||||||
data_blocks);
|
data_blocks);
|
||||||
|
|
||||||
// Mini Fat
|
// Mini Fat
|
||||||
BlockList sbat =
|
BlockList sbat =
|
||||||
SmallBlockTableReader.getSmallDocumentBlocks(
|
SmallBlockTableReader.getSmallDocumentBlocks(
|
||||||
bigBlockSize, data_blocks, properties.getRoot(),
|
bigBlockSize, data_blocks, properties.getRoot(),
|
||||||
header_block_reader.getSBATStart()
|
header_block.getSBATStart()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void displayHeader(HeaderBlockReader header_block_reader) throws Exception {
|
public static void displayHeader(HeaderBlock header_block) throws Exception {
|
||||||
System.out.println("Header Details:");
|
System.out.println("Header Details:");
|
||||||
System.out.println(" Block size: " + header_block_reader.getBigBlockSize());
|
System.out.println(" Block size: " + header_block.getBigBlockSize());
|
||||||
System.out.println(" BAT (FAT) header blocks: " + header_block_reader.getBATArray().length);
|
System.out.println(" BAT (FAT) header blocks: " + header_block.getBATArray().length);
|
||||||
System.out.println(" BAT (FAT) block count: " + header_block_reader.getBATCount());
|
System.out.println(" BAT (FAT) block count: " + header_block.getBATCount());
|
||||||
System.out.println(" XBAT (FAT) block count: " + header_block_reader.getXBATCount());
|
System.out.println(" XBAT (FAT) block count: " + header_block.getXBATCount());
|
||||||
System.out.println(" XBAT (FAT) block 1 at: " + header_block_reader.getXBATIndex());
|
System.out.println(" XBAT (FAT) block 1 at: " + header_block.getXBATIndex());
|
||||||
System.out.println(" SBAT (MiniFAT) block count: " + header_block_reader.getSBATCount());
|
System.out.println(" SBAT (MiniFAT) block count: " + header_block.getSBATCount());
|
||||||
System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block_reader.getSBATStart());
|
System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block.getSBATStart());
|
||||||
System.out.println(" Property table at: " + header_block_reader.getPropertyStart());
|
System.out.println(" Property table at: " + header_block.getPropertyStart());
|
||||||
System.out.println("");
|
System.out.println("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ import org.apache.poi.poifs.property.Property;
|
||||||
import org.apache.poi.poifs.property.PropertyTable;
|
import org.apache.poi.poifs.property.PropertyTable;
|
||||||
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
||||||
import org.apache.poi.poifs.storage.BlockList;
|
import org.apache.poi.poifs.storage.BlockList;
|
||||||
import org.apache.poi.poifs.storage.HeaderBlockReader;
|
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||||
import org.apache.poi.poifs.storage.RawDataBlockList;
|
import org.apache.poi.poifs.storage.RawDataBlockList;
|
||||||
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
||||||
|
|
||||||
|
@ -75,32 +75,32 @@ public class POIFSReader
|
||||||
registryClosed = true;
|
registryClosed = true;
|
||||||
|
|
||||||
// read the header block from the stream
|
// read the header block from the stream
|
||||||
HeaderBlockReader header_block_reader = new HeaderBlockReader(stream);
|
HeaderBlock header_block = new HeaderBlock(stream);
|
||||||
|
|
||||||
// read the rest of the stream into blocks
|
// read the rest of the stream into blocks
|
||||||
RawDataBlockList data_blocks = new RawDataBlockList(stream, header_block_reader.getBigBlockSize());
|
RawDataBlockList data_blocks = new RawDataBlockList(stream, header_block.getBigBlockSize());
|
||||||
|
|
||||||
// set up the block allocation table (necessary for the
|
// set up the block allocation table (necessary for the
|
||||||
// data_blocks to be manageable
|
// data_blocks to be manageable
|
||||||
new BlockAllocationTableReader(header_block_reader.getBigBlockSize(),
|
new BlockAllocationTableReader(header_block.getBigBlockSize(),
|
||||||
header_block_reader.getBATCount(),
|
header_block.getBATCount(),
|
||||||
header_block_reader.getBATArray(),
|
header_block.getBATArray(),
|
||||||
header_block_reader.getXBATCount(),
|
header_block.getXBATCount(),
|
||||||
header_block_reader.getXBATIndex(),
|
header_block.getXBATIndex(),
|
||||||
data_blocks);
|
data_blocks);
|
||||||
|
|
||||||
// get property table from the document
|
// get property table from the document
|
||||||
PropertyTable properties =
|
PropertyTable properties =
|
||||||
new PropertyTable(header_block_reader.getBigBlockSize(),
|
new PropertyTable(header_block.getBigBlockSize(),
|
||||||
header_block_reader.getPropertyStart(),
|
header_block.getPropertyStart(),
|
||||||
data_blocks);
|
data_blocks);
|
||||||
|
|
||||||
// process documents
|
// process documents
|
||||||
processProperties(SmallBlockTableReader
|
processProperties(SmallBlockTableReader
|
||||||
.getSmallDocumentBlocks(
|
.getSmallDocumentBlocks(
|
||||||
header_block_reader.getBigBlockSize(),
|
header_block.getBigBlockSize(),
|
||||||
data_blocks, properties.getRoot(),
|
data_blocks, properties.getRoot(),
|
||||||
header_block_reader.getSBATStart()),
|
header_block.getSBATStart()),
|
||||||
data_blocks, properties.getRoot()
|
data_blocks, properties.getRoot()
|
||||||
.getChildren(), new POIFSDocumentPath());
|
.getChildren(), new POIFSDocumentPath());
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ import org.apache.poi.poifs.storage.BlockAllocationTableWriter;
|
||||||
import org.apache.poi.poifs.storage.BlockList;
|
import org.apache.poi.poifs.storage.BlockList;
|
||||||
import org.apache.poi.poifs.storage.BlockWritable;
|
import org.apache.poi.poifs.storage.BlockWritable;
|
||||||
import org.apache.poi.poifs.storage.HeaderBlockConstants;
|
import org.apache.poi.poifs.storage.HeaderBlockConstants;
|
||||||
import org.apache.poi.poifs.storage.HeaderBlockReader;
|
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||||
import org.apache.poi.poifs.storage.HeaderBlockWriter;
|
import org.apache.poi.poifs.storage.HeaderBlockWriter;
|
||||||
import org.apache.poi.poifs.storage.RawDataBlockList;
|
import org.apache.poi.poifs.storage.RawDataBlockList;
|
||||||
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
||||||
|
@ -146,12 +146,12 @@ public class POIFSFileSystem
|
||||||
this();
|
this();
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
|
|
||||||
HeaderBlockReader header_block_reader;
|
HeaderBlock header_block;
|
||||||
RawDataBlockList data_blocks;
|
RawDataBlockList data_blocks;
|
||||||
try {
|
try {
|
||||||
// read the header block from the stream
|
// read the header block from the stream
|
||||||
header_block_reader = new HeaderBlockReader(stream);
|
header_block = new HeaderBlock(stream);
|
||||||
bigBlockSize = header_block_reader.getBigBlockSize();
|
bigBlockSize = header_block.getBigBlockSize();
|
||||||
|
|
||||||
// read the rest of the stream into blocks
|
// read the rest of the stream into blocks
|
||||||
data_blocks = new RawDataBlockList(stream, bigBlockSize);
|
data_blocks = new RawDataBlockList(stream, bigBlockSize);
|
||||||
|
@ -163,29 +163,29 @@ public class POIFSFileSystem
|
||||||
|
|
||||||
// set up the block allocation table (necessary for the
|
// set up the block allocation table (necessary for the
|
||||||
// data_blocks to be manageable
|
// data_blocks to be manageable
|
||||||
new BlockAllocationTableReader(header_block_reader.getBigBlockSize(),
|
new BlockAllocationTableReader(header_block.getBigBlockSize(),
|
||||||
header_block_reader.getBATCount(),
|
header_block.getBATCount(),
|
||||||
header_block_reader.getBATArray(),
|
header_block.getBATArray(),
|
||||||
header_block_reader.getXBATCount(),
|
header_block.getXBATCount(),
|
||||||
header_block_reader.getXBATIndex(),
|
header_block.getXBATIndex(),
|
||||||
data_blocks);
|
data_blocks);
|
||||||
|
|
||||||
// get property table from the document
|
// get property table from the document
|
||||||
PropertyTable properties =
|
PropertyTable properties =
|
||||||
new PropertyTable(bigBlockSize,
|
new PropertyTable(bigBlockSize,
|
||||||
header_block_reader.getPropertyStart(),
|
header_block.getPropertyStart(),
|
||||||
data_blocks);
|
data_blocks);
|
||||||
|
|
||||||
// init documents
|
// init documents
|
||||||
processProperties(
|
processProperties(
|
||||||
SmallBlockTableReader.getSmallDocumentBlocks(
|
SmallBlockTableReader.getSmallDocumentBlocks(
|
||||||
bigBlockSize, data_blocks, properties.getRoot(),
|
bigBlockSize, data_blocks, properties.getRoot(),
|
||||||
header_block_reader.getSBATStart()
|
header_block.getSBATStart()
|
||||||
),
|
),
|
||||||
data_blocks,
|
data_blocks,
|
||||||
properties.getRoot().getChildren(),
|
properties.getRoot().getChildren(),
|
||||||
null,
|
null,
|
||||||
header_block_reader.getPropertyStart()
|
header_block.getPropertyStart()
|
||||||
);
|
);
|
||||||
|
|
||||||
// For whatever reason CLSID of root is always 0.
|
// For whatever reason CLSID of root is always 0.
|
||||||
|
|
|
@ -30,22 +30,31 @@ import static org.apache.poi.poifs.storage.HeaderBlockConstants._xbat_start_offs
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.poi.poifs.common.POIFSBigBlockSize;
|
import org.apache.poi.poifs.common.POIFSBigBlockSize;
|
||||||
import org.apache.poi.poifs.common.POIFSConstants;
|
import org.apache.poi.poifs.common.POIFSConstants;
|
||||||
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
|
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
|
||||||
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
import org.apache.poi.util.HexDump;
|
import org.apache.poi.util.HexDump;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
|
import org.apache.poi.util.IntegerField;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.LittleEndianConsts;
|
import org.apache.poi.util.LittleEndianConsts;
|
||||||
|
import org.apache.poi.util.LongField;
|
||||||
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
import org.apache.poi.util.ShortField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The block containing the archive header
|
* The block containing the archive header
|
||||||
*
|
|
||||||
* @author Marc Johnson (mjohnson at apache dot org)
|
|
||||||
*/
|
*/
|
||||||
public final class HeaderBlockReader {
|
public final class HeaderBlock {
|
||||||
|
private static final POILogger _logger =
|
||||||
|
POILogFactory.getLogger(HeaderBlock.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What big block size the file uses. Most files
|
* What big block size the file uses. Most files
|
||||||
* use 512 bytes, but a few use 4096
|
* use 512 bytes, but a few use 4096
|
||||||
|
@ -56,40 +65,43 @@ public final class HeaderBlockReader {
|
||||||
* number of big block allocation table blocks (int).
|
* number of big block allocation table blocks (int).
|
||||||
* (Number of FAT Sectors in Microsoft parlance)
|
* (Number of FAT Sectors in Microsoft parlance)
|
||||||
*/
|
*/
|
||||||
private final int _bat_count;
|
private int _bat_count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start of the property set block (int index of the property set
|
* Start of the property set block (int index of the property set
|
||||||
* chain's first big block).
|
* chain's first big block).
|
||||||
*/
|
*/
|
||||||
private final int _property_start;
|
private int _property_start;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* start of the small block allocation table (int index of small
|
* start of the small block allocation table (int index of small
|
||||||
* block allocation table's first big block)
|
* block allocation table's first big block)
|
||||||
*/
|
*/
|
||||||
private final int _sbat_start;
|
private int _sbat_start;
|
||||||
/**
|
/**
|
||||||
* Number of small block allocation table blocks (int)
|
* Number of small block allocation table blocks (int)
|
||||||
* (Number of MiniFAT Sectors in Microsoft parlance)
|
* (Number of MiniFAT Sectors in Microsoft parlance)
|
||||||
*/
|
*/
|
||||||
private final int _sbat_count;
|
private int _sbat_count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Big block index for extension to the big block allocation table
|
* Big block index for extension to the big block allocation table
|
||||||
*/
|
*/
|
||||||
private final int _xbat_start;
|
private int _xbat_start;
|
||||||
/**
|
/**
|
||||||
* Number of big block allocation table blocks (int)
|
* Number of big block allocation table blocks (int)
|
||||||
* (Number of DIFAT Sectors in Microsoft parlance)
|
* (Number of DIFAT Sectors in Microsoft parlance)
|
||||||
*/
|
*/
|
||||||
private final int _xbat_count;
|
private int _xbat_count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data
|
* The data. Only ever 512 bytes, because 4096 byte
|
||||||
|
* files use zeros for the extra header space.
|
||||||
*/
|
*/
|
||||||
private final byte[] _data;
|
private final byte[] _data;
|
||||||
|
|
||||||
|
private static final byte _default_value = ( byte ) 0xFF;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create a new HeaderBlockReader from an InputStream
|
* create a new HeaderBlockReader from an InputStream
|
||||||
*
|
*
|
||||||
|
@ -97,7 +109,7 @@ public final class HeaderBlockReader {
|
||||||
*
|
*
|
||||||
* @exception IOException on errors or bad data
|
* @exception IOException on errors or bad data
|
||||||
*/
|
*/
|
||||||
public HeaderBlockReader(InputStream stream) throws IOException {
|
public HeaderBlock(InputStream stream) throws IOException {
|
||||||
// Grab the first 512 bytes
|
// Grab the first 512 bytes
|
||||||
// (For 4096 sized blocks, the remaining 3584 bytes are zero)
|
// (For 4096 sized blocks, the remaining 3584 bytes are zero)
|
||||||
// Then, process the contents
|
// Then, process the contents
|
||||||
|
@ -111,11 +123,11 @@ public final class HeaderBlockReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HeaderBlockReader(ByteBuffer buffer) throws IOException {
|
public HeaderBlock(ByteBuffer buffer) throws IOException {
|
||||||
this(buffer.array());
|
this(buffer.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
private HeaderBlockReader(byte[] data) throws IOException {
|
private HeaderBlock(byte[] data) throws IOException {
|
||||||
this._data = data;
|
this._data = data;
|
||||||
|
|
||||||
// verify signature
|
// verify signature
|
||||||
|
@ -144,22 +156,65 @@ public final class HeaderBlockReader {
|
||||||
|
|
||||||
|
|
||||||
// Figure out our block size
|
// Figure out our block size
|
||||||
switch (_data[30]) {
|
if (_data[30] == 12) {
|
||||||
case 12:
|
this.bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS;
|
||||||
bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS; break;
|
} else if(_data[30] == 9) {
|
||||||
case 9:
|
this.bigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
|
||||||
bigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS; break;
|
} else {
|
||||||
default:
|
throw new IOException("Unsupported blocksize (2^"+ _data[30] + "). Expected 2^9 or 2^12.");
|
||||||
throw new IOException("Unsupported blocksize (2^"
|
|
||||||
+ _data[30] + "). Expected 2^9 or 2^12.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_bat_count = getInt(_bat_count_offset, _data);
|
// Setup the fields to read and write the counts and starts
|
||||||
_property_start = getInt(_property_start_offset, _data);
|
_bat_count = new IntegerField(_bat_count_offset, data).get();
|
||||||
_sbat_start = getInt(_sbat_start_offset, _data);
|
_property_start = new IntegerField(_property_start_offset,_data).get();
|
||||||
_sbat_count = getInt(_sbat_block_count_offset, _data);
|
_sbat_start = new IntegerField(_sbat_start_offset, _data).get();
|
||||||
_xbat_start = getInt(_xbat_start_offset, _data);
|
_sbat_count = new IntegerField(_sbat_block_count_offset, _data).get();
|
||||||
_xbat_count = getInt(_xbat_count_offset, _data);
|
_xbat_start = new IntegerField(_xbat_start_offset, _data).get();
|
||||||
|
_xbat_count = new IntegerField(_xbat_count_offset, _data).get();
|
||||||
|
|
||||||
|
// Sanity check values
|
||||||
|
if(_bat_count > _max_bats_in_header) {
|
||||||
|
_logger.log(POILogger.WARN, "Too many BAT blocks listed in header, found "
|
||||||
|
+ _bat_count + " but the maximum is " + _max_bats_in_header);
|
||||||
|
_bat_count = _max_bats_in_header;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a single instance initialized with default values
|
||||||
|
*/
|
||||||
|
public HeaderBlock(POIFSBigBlockSize bigBlockSize) throws IOException
|
||||||
|
{
|
||||||
|
this.bigBlockSize = bigBlockSize;
|
||||||
|
|
||||||
|
// Our data is always 512 big no matter what
|
||||||
|
_data = new byte[ POIFSConstants.SMALLER_BIG_BLOCK_SIZE ];
|
||||||
|
Arrays.fill(_data, _default_value);
|
||||||
|
|
||||||
|
// Set all the default values
|
||||||
|
new LongField(_signature_offset, _signature, _data);
|
||||||
|
new IntegerField(0x08, 0, _data);
|
||||||
|
new IntegerField(0x0c, 0, _data);
|
||||||
|
new IntegerField(0x10, 0, _data);
|
||||||
|
new IntegerField(0x14, 0, _data);
|
||||||
|
new ShortField(0x18, ( short ) 0x3b, _data);
|
||||||
|
new ShortField(0x1a, ( short ) 0x3, _data);
|
||||||
|
new ShortField(0x1c, ( short ) -2, _data);
|
||||||
|
|
||||||
|
new ShortField(0x1e, bigBlockSize.getHeaderValue(), _data);
|
||||||
|
new IntegerField(0x20, 0x6, _data);
|
||||||
|
new IntegerField(0x24, 0, _data);
|
||||||
|
new IntegerField(0x28, 0, _data);
|
||||||
|
new IntegerField(0x34, 0, _data);
|
||||||
|
new IntegerField(0x38, 0x1000, _data);
|
||||||
|
|
||||||
|
// Initialise the variables
|
||||||
|
_bat_count = 0;
|
||||||
|
_sbat_count = 0;
|
||||||
|
_xbat_count = 0;
|
||||||
|
_property_start = POIFSConstants.END_OF_CHAIN;
|
||||||
|
_sbat_start = POIFSConstants.END_OF_CHAIN;
|
||||||
|
_xbat_start = POIFSConstants.END_OF_CHAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] readFirst512(InputStream stream) throws IOException {
|
private static byte[] readFirst512(InputStream stream) throws IOException {
|
||||||
|
@ -173,10 +228,6 @@ public final class HeaderBlockReader {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getInt(int offset, byte[] data) {
|
|
||||||
return LittleEndian.getInt(data, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String longToHex(long value) {
|
private static String longToHex(long value) {
|
||||||
return new String(HexDump.longToHex(value));
|
return new String(HexDump.longToHex(value));
|
||||||
}
|
}
|
||||||
|
@ -225,14 +276,15 @@ public final class HeaderBlockReader {
|
||||||
/**
|
/**
|
||||||
* Returns the offsets to the first (up to) 109
|
* Returns the offsets to the first (up to) 109
|
||||||
* BAT sectors.
|
* BAT sectors.
|
||||||
* Any additional BAT sectors
|
* Any additional BAT sectors are held in the XBAT (DIFAT)
|
||||||
|
* sectors in a chain.
|
||||||
* @return BAT offset array
|
* @return BAT offset array
|
||||||
*/
|
*/
|
||||||
public int[] getBATArray() {
|
public int[] getBATArray() {
|
||||||
int[] result = new int[ _max_bats_in_header ];
|
// Read them in
|
||||||
|
int[] result = new int[ _bat_count ];
|
||||||
int offset = _bat_array_offset;
|
int offset = _bat_array_offset;
|
||||||
|
for (int j = 0; j < _bat_count; j++) {
|
||||||
for (int j = 0; j < _max_bats_in_header; j++) {
|
|
||||||
result[ j ] = LittleEndian.getInt(_data, offset);
|
result[ j ] = LittleEndian.getInt(_data, offset);
|
||||||
offset += LittleEndianConsts.INT_SIZE;
|
offset += LittleEndianConsts.INT_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -259,4 +311,33 @@ public final class HeaderBlockReader {
|
||||||
public POIFSBigBlockSize getBigBlockSize() {
|
public POIFSBigBlockSize getBigBlockSize() {
|
||||||
return bigBlockSize;
|
return bigBlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the block's data to an OutputStream
|
||||||
|
*
|
||||||
|
* @param stream the OutputStream to which the stored data should
|
||||||
|
* be written
|
||||||
|
*
|
||||||
|
* @exception IOException on problems writing to the specified
|
||||||
|
* stream
|
||||||
|
*/
|
||||||
|
void writeData(final OutputStream stream)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
// Update the counts and start positions
|
||||||
|
new IntegerField(_bat_count_offset, _bat_count, _data);
|
||||||
|
new IntegerField(_property_start_offset, _property_start, _data);
|
||||||
|
new IntegerField(_sbat_start_offset, _sbat_start, _data);
|
||||||
|
new IntegerField(_sbat_block_count_offset, _sbat_count, _data);
|
||||||
|
new IntegerField(_xbat_start_offset, _xbat_start, _data);
|
||||||
|
new IntegerField(_xbat_count_offset, _xbat_count, _data);
|
||||||
|
|
||||||
|
// Write the main data out
|
||||||
|
stream.write(_data, 0, 512);
|
||||||
|
|
||||||
|
// Now do the padding if needed
|
||||||
|
for(int i=POIFSConstants.SMALLER_BIG_BLOCK_SIZE; i<POIFSConstants.LARGER_BIG_BLOCK_SIZE; i++) {
|
||||||
|
stream.write(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ import junit.framework.TestCase;
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||||
import org.apache.poi.poifs.common.POIFSBigBlockSize;
|
import org.apache.poi.poifs.common.POIFSBigBlockSize;
|
||||||
import org.apache.poi.poifs.storage.HeaderBlockReader;
|
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||||
import org.apache.poi.poifs.storage.RawDataBlockList;
|
import org.apache.poi.poifs.storage.RawDataBlockList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,14 +184,14 @@ public final class TestPOIFSFileSystem extends TestCase {
|
||||||
InputStream inp = _samples.openResourceAsStream("BlockSize4096.zvi");
|
InputStream inp = _samples.openResourceAsStream("BlockSize4096.zvi");
|
||||||
|
|
||||||
// First up, check that we can process the header properly
|
// First up, check that we can process the header properly
|
||||||
HeaderBlockReader header_block_reader = new HeaderBlockReader(inp);
|
HeaderBlock header_block = new HeaderBlock(inp);
|
||||||
POIFSBigBlockSize bigBlockSize = header_block_reader.getBigBlockSize();
|
POIFSBigBlockSize bigBlockSize = header_block.getBigBlockSize();
|
||||||
assertEquals(4096, bigBlockSize.getBigBlockSize());
|
assertEquals(4096, bigBlockSize.getBigBlockSize());
|
||||||
|
|
||||||
// Check the fat info looks sane
|
// Check the fat info looks sane
|
||||||
assertEquals(109, header_block_reader.getBATArray().length);
|
assertEquals(1, header_block.getBATArray().length);
|
||||||
assertTrue(header_block_reader.getBATCount() > 0);
|
assertEquals(1, header_block.getBATCount());
|
||||||
assertEquals(0, header_block_reader.getXBATCount());
|
assertEquals(0, header_block.getXBATCount());
|
||||||
|
|
||||||
// Now check we can get the basic fat
|
// Now check we can get the basic fat
|
||||||
RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
|
RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
|
||||||
|
|
|
@ -33,8 +33,8 @@ public final class AllPOIFSStorageTests {
|
||||||
result.addTestSuite(TestBlockAllocationTableWriter.class);
|
result.addTestSuite(TestBlockAllocationTableWriter.class);
|
||||||
result.addTestSuite(TestBlockListImpl.class);
|
result.addTestSuite(TestBlockListImpl.class);
|
||||||
result.addTestSuite(TestDocumentBlock.class);
|
result.addTestSuite(TestDocumentBlock.class);
|
||||||
result.addTestSuite(TestHeaderBlockReader.class);
|
result.addTestSuite(TestHeaderBlockReading.class);
|
||||||
result.addTestSuite(TestHeaderBlockWriter.class);
|
result.addTestSuite(TestHeaderBlockWriting.class);
|
||||||
result.addTestSuite(TestPropertyBlock.class);
|
result.addTestSuite(TestPropertyBlock.class);
|
||||||
result.addTestSuite(TestRawDataBlock.class);
|
result.addTestSuite(TestRawDataBlock.class);
|
||||||
result.addTestSuite(TestRawDataBlockList.class);
|
result.addTestSuite(TestRawDataBlockList.class);
|
||||||
|
|
|
@ -405,10 +405,10 @@ public final class TestBlockAllocationTableReader extends TestCase {
|
||||||
|
|
||||||
// similar code to POIFSFileSystem.<init>:
|
// similar code to POIFSFileSystem.<init>:
|
||||||
InputStream stream = new ByteArrayInputStream(data);
|
InputStream stream = new ByteArrayInputStream(data);
|
||||||
HeaderBlockReader hb;
|
HeaderBlock hb;
|
||||||
RawDataBlockList dataBlocks;
|
RawDataBlockList dataBlocks;
|
||||||
try {
|
try {
|
||||||
hb = new HeaderBlockReader(stream);
|
hb = new HeaderBlock(stream);
|
||||||
dataBlocks = new RawDataBlockList(stream, bigBlockSize);
|
dataBlocks = new RawDataBlockList(stream, bigBlockSize);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
@ -419,7 +419,11 @@ public final class TestBlockAllocationTableReader extends TestCase {
|
||||||
hb.getXBATIndex(), dataBlocks);
|
hb.getXBATIndex(), dataBlocks);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// expected during successful test
|
// expected during successful test
|
||||||
assertEquals("Block count 538976257 is too high. POI maximum is 65535.", e.getMessage());
|
assertEquals(
|
||||||
|
"Your file contains 0 sectors, but the initial DIFAT array at index 0 referenced block # 538976288. This isn't allowed and your file is corrupt",
|
||||||
|
e.getMessage()
|
||||||
|
);
|
||||||
|
// assertEquals("Block count 538976257 is too high. POI maximum is 65535.", e.getMessage());
|
||||||
} catch (OutOfMemoryError e) {
|
} catch (OutOfMemoryError e) {
|
||||||
if (e.getStackTrace()[1].getMethodName().equals("testBadSectorAllocationTableSize")) {
|
if (e.getStackTrace()[1].getMethodName().equals("testBadSectorAllocationTableSize")) {
|
||||||
throw new AssertionFailedError("Identified bug 48085");
|
throw new AssertionFailedError("Identified bug 48085");
|
||||||
|
|
|
@ -27,7 +27,7 @@ import junit.framework.TestCase;
|
||||||
*
|
*
|
||||||
* @author Marc Johnson
|
* @author Marc Johnson
|
||||||
*/
|
*/
|
||||||
public final class TestHeaderBlockReader extends TestCase {
|
public final class TestHeaderBlockReading extends TestCase {
|
||||||
|
|
||||||
public void testConstructors() throws IOException {
|
public void testConstructors() throws IOException {
|
||||||
String[] hexData = {
|
String[] hexData = {
|
||||||
|
@ -49,7 +49,7 @@ public final class TestHeaderBlockReader extends TestCase {
|
||||||
"FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF",
|
"FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF",
|
||||||
};
|
};
|
||||||
byte[] content = RawDataUtil.decode(hexData);
|
byte[] content = RawDataUtil.decode(hexData);
|
||||||
HeaderBlockReader block = new HeaderBlockReader(new ByteArrayInputStream(content));
|
HeaderBlock block = new HeaderBlock(new ByteArrayInputStream(content));
|
||||||
|
|
||||||
assertEquals(-2, block.getPropertyStart());
|
assertEquals(-2, block.getPropertyStart());
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ public final class TestHeaderBlockReader extends TestCase {
|
||||||
|
|
||||||
System.arraycopy(content, 0, shortblock, 0, 511);
|
System.arraycopy(content, 0, shortblock, 0, 511);
|
||||||
try {
|
try {
|
||||||
block = new HeaderBlockReader(new ByteArrayInputStream(shortblock));
|
block = new HeaderBlock(new ByteArrayInputStream(shortblock));
|
||||||
fail("Should have caught IOException reading a short block");
|
fail("Should have caught IOException reading a short block");
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public final class TestHeaderBlockReader extends TestCase {
|
||||||
for (int index = 0; index < 8; index++) {
|
for (int index = 0; index < 8; index++) {
|
||||||
content[index] = (byte) (content[index] - 1);
|
content[index] = (byte) (content[index] - 1);
|
||||||
try {
|
try {
|
||||||
block = new HeaderBlockReader(new ByteArrayInputStream(content));
|
block = new HeaderBlock(new ByteArrayInputStream(content));
|
||||||
fail("Should have caught IOException corrupting byte " + index);
|
fail("Should have caught IOException corrupting byte " + index);
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.apache.poi.util.LittleEndianConsts;
|
||||||
*
|
*
|
||||||
* @author Marc Johnson
|
* @author Marc Johnson
|
||||||
*/
|
*/
|
||||||
public final class TestHeaderBlockWriter extends TestCase {
|
public final class TestHeaderBlockWriting extends TestCase {
|
||||||
|
|
||||||
private static void confirmEqual(String[] expectedDataHexDumpLines, byte[] actual) {
|
private static void confirmEqual(String[] expectedDataHexDumpLines, byte[] actual) {
|
||||||
byte[] expected = RawDataUtil.decode(expectedDataHexDumpLines);
|
byte[] expected = RawDataUtil.decode(expectedDataHexDumpLines);
|
||||||
|
@ -78,8 +78,8 @@ public final class TestHeaderBlockWriter extends TestCase {
|
||||||
block.setPropertyStart(0x87654321);
|
block.setPropertyStart(0x87654321);
|
||||||
output = new ByteArrayOutputStream(512);
|
output = new ByteArrayOutputStream(512);
|
||||||
block.writeBlocks(output);
|
block.writeBlocks(output);
|
||||||
assertEquals(0x87654321, new HeaderBlockReader(new ByteArrayInputStream(output
|
assertEquals(0x87654321, new HeaderBlock(
|
||||||
.toByteArray())).getPropertyStart());
|
new ByteArrayInputStream(output.toByteArray())).getPropertyStart());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
Loading…
Reference in New Issue