Resolve bug #49139 - don't assume that the block size is always 512 bytes. Instead of hard coding this value in, pass around the new POIFSBigBlockSize object that holds the size and various helper subsizes. Should now be possible to open 4k block files without error.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@937834 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2010-04-25 17:35:56 +00:00
parent 0b4df9519b
commit a3899a57d8
41 changed files with 658 additions and 267 deletions

View File

@ -0,0 +1,58 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.poifs.common;
import org.apache.poi.util.LittleEndianConsts;
/**
* <p>A class describing attributes of the Big Block Size</p>
*/
public final class POIFSBigBlockSize
{
private int bigBlockSize;
private short headerValue;
protected POIFSBigBlockSize(int bigBlockSize, short headerValue) {
this.bigBlockSize = bigBlockSize;
this.headerValue = headerValue;
}
public int getBigBlockSize() {
return bigBlockSize;
}
public short getHeaderValue() {
return headerValue;
}
public int getPropertiesPerBlock() {
return bigBlockSize / POIFSConstants.PROPERTY_SIZE;
}
public int getBATEntriesPerBlock() {
return bigBlockSize / LittleEndianConsts.INT_SIZE;
}
public int getXBATEntriesPerBlock() {
return getBATEntriesPerBlock() - 1;
}
public int getNextXBATChainOffset() {
return getXBATEntriesPerBlock() * LittleEndianConsts.INT_SIZE;
}
}

View File

@ -21,16 +21,17 @@ package org.apache.poi.poifs.common;
/**
* <p>A repository for constants shared by POI classes.</p>
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
public interface POIFSConstants
{
/** Most files use 512 bytes as their big block size */
public static final int BIG_BLOCK_SIZE = 0x0200;
public static final int SMALLER_BIG_BLOCK_SIZE = 0x0200;
public static final POIFSBigBlockSize SMALLER_BIG_BLOCK_SIZE_DETAILS =
new POIFSBigBlockSize(SMALLER_BIG_BLOCK_SIZE, (short)9);
/** Some use 4096 bytes */
public static final int LARGER_BIG_BLOCK_SIZE = 0x1000;
public static final POIFSBigBlockSize LARGER_BIG_BLOCK_SIZE_DETAILS =
new POIFSBigBlockSize(LARGER_BIG_BLOCK_SIZE, (short)12);
public static final int PROPERTY_SIZE = 0x0080;

View File

@ -0,0 +1,159 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.poifs.dev;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
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.storage.BlockAllocationTableReader;
import org.apache.poi.poifs.storage.BlockList;
import org.apache.poi.poifs.storage.HeaderBlockReader;
import org.apache.poi.poifs.storage.ListManagedBlock;
import org.apache.poi.poifs.storage.RawDataBlockList;
import org.apache.poi.poifs.storage.SmallBlockTableReader;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.IntList;
/**
* A very low level debugging tool, for printing out core
* information on the headers and FAT blocks.
* You probably only want to use this if you're trying
* to understand POIFS, or if you're trying to track
* down the source of corruption in a file.
*/
public class POIFSHeaderDumper {
/**
* Display the entries of multiple POIFS files
*
* @param args the names of the files to be displayed
*/
public static void main(final String args[]) throws Exception {
if (args.length == 0) {
System.err.println("Must specify at least one file to view");
System.exit(1);
}
for (int j = 0; j < args.length; j++) {
viewFile(args[j]);
}
}
public static void viewFile(final String filename) throws Exception {
InputStream inp = new FileInputStream(filename);
// Header
HeaderBlockReader header_block_reader =
new HeaderBlockReader(inp);
displayHeader(header_block_reader);
// Raw blocks
POIFSBigBlockSize bigBlockSize = header_block_reader.getBigBlockSize();
RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
displayRawBlocksSummary(data_blocks);
// Main FAT Table
BlockAllocationTableReader batReader =
new BlockAllocationTableReader(
header_block_reader.getBigBlockSize(),
header_block_reader.getBATCount(),
header_block_reader.getBATArray(),
header_block_reader.getXBATCount(),
header_block_reader.getXBATIndex(),
data_blocks);
displayBATReader(batReader);
// Properties Table
PropertyTable properties =
new PropertyTable(
header_block_reader.getBigBlockSize(),
header_block_reader.getPropertyStart(),
data_blocks);
// Mini Fat
BlockList sbat =
SmallBlockTableReader.getSmallDocumentBlocks(
bigBlockSize, data_blocks, properties.getRoot(),
header_block_reader.getSBATStart()
);
}
public static void displayHeader(HeaderBlockReader header_block_reader) throws Exception {
System.out.println("Header Details:");
System.out.println(" Block size: " + header_block_reader.getBigBlockSize());
System.out.println(" BAT (FAT) header blocks: " + header_block_reader.getBATArray().length);
System.out.println(" BAT (FAT) block count: " + header_block_reader.getBATCount());
System.out.println(" XBAT (FAT) block count: " + header_block_reader.getXBATCount());
System.out.println(" XBAT (FAT) block 1 at: " + header_block_reader.getXBATIndex());
System.out.println(" SBAT (MiniFAT) block count: " + header_block_reader.getSBATCount());
System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block_reader.getSBATStart());
System.out.println(" Property table at: " + header_block_reader.getPropertyStart());
System.out.println("");
}
public static void displayRawBlocksSummary(RawDataBlockList data_blocks) throws Exception {
System.out.println("Raw Blocks Details:");
System.out.println(" Number of blocks: " + data_blocks.blockCount());
Method gbm = data_blocks.getClass().getSuperclass().getDeclaredMethod("get", int.class);
gbm.setAccessible(true);
for(int i=0; i<Math.min(16, data_blocks.blockCount()); i++) {
ListManagedBlock block = (ListManagedBlock)gbm.invoke(data_blocks, new Integer(i));
byte[] data = new byte[Math.min(48, block.getData().length)];
System.arraycopy(block.getData(), 0, data, 0, data.length);
System.out.println(" Block #" + i + ":");
System.out.println(HexDump.dump(data, 0, 0));
}
System.out.println("");
}
public static void displayBATReader(BlockAllocationTableReader batReader) throws Exception {
System.out.println("Sectors, as referenced from the FAT:");
Field entriesF = batReader.getClass().getDeclaredField("_entries");
entriesF.setAccessible(true);
IntList entries = (IntList)entriesF.get(batReader);
for(int i=0; i<entries.size(); i++) {
int bn = entries.get(i);
String bnS = Integer.toString(bn);
if(bn == POIFSConstants.END_OF_CHAIN) {
bnS = "End Of Chain";
} else if(bn == POIFSConstants.DIFAT_SECTOR_BLOCK) {
bnS = "DI Fat Block";
} else if(bn == POIFSConstants.FAT_SECTOR_BLOCK) {
bnS = "Normal Fat Block";
}
System.out.println(" Block # " + i + " -> " + bnS);
}
System.out.println("");
}
}

View File

@ -82,7 +82,8 @@ public class POIFSReader
// set up the block allocation table (necessary for the
// data_blocks to be manageable
new BlockAllocationTableReader(header_block_reader.getBATCount(),
new BlockAllocationTableReader(header_block_reader.getBigBlockSize(),
header_block_reader.getBATCount(),
header_block_reader.getBATArray(),
header_block_reader.getXBATCount(),
header_block_reader.getXBATIndex(),
@ -90,14 +91,17 @@ public class POIFSReader
// get property table from the document
PropertyTable properties =
new PropertyTable(header_block_reader.getPropertyStart(),
new PropertyTable(header_block_reader.getBigBlockSize(),
header_block_reader.getPropertyStart(),
data_blocks);
// process documents
processProperties(SmallBlockTableReader
.getSmallDocumentBlocks(data_blocks, properties
.getRoot(), header_block_reader
.getSBATStart()), data_blocks, properties.getRoot()
.getSmallDocumentBlocks(
header_block_reader.getBigBlockSize(),
data_blocks, properties.getRoot(),
header_block_reader.getSBATStart()),
data_blocks, properties.getRoot()
.getChildren(), new POIFSDocumentPath());
}

View File

@ -26,6 +26,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.dev.POIFSViewable;
import org.apache.poi.poifs.property.DocumentProperty;
@ -48,12 +49,14 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
private static final SmallDocumentBlock[] EMPTY_SMALL_BLOCK_ARRAY = { };
private DocumentProperty _property;
private int _size;
private final POIFSBigBlockSize _bigBigBlockSize;
// one of these stores will be valid
private SmallBlockStore _small_store;
private BigBlockStore _big_store;
/**
/**
* Constructor from large blocks
*
* @param name the name of the POIFSDocument
@ -62,9 +65,18 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
*/
public POIFSDocument(String name, RawDataBlock[] blocks, int length) throws IOException {
_size = length;
_big_store = new BigBlockStore(convertRawBlocksToBigBlocks(blocks));
if(blocks.length == 0) {
_bigBigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
} else {
_bigBigBlockSize = (blocks[0].getBigBlockSize() == POIFSConstants.SMALLER_BIG_BLOCK_SIZE ?
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS :
POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS
);
}
_big_store = new BigBlockStore(_bigBigBlockSize, convertRawBlocksToBigBlocks(blocks));
_property = new DocumentProperty(name, _size);
_small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY);
_small_store = new SmallBlockStore(_bigBigBlockSize, EMPTY_SMALL_BLOCK_ARRAY);
_property.setDocument(this);
}
@ -94,9 +106,16 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
*/
public POIFSDocument(String name, SmallDocumentBlock[] blocks, int length) {
_size = length;
_big_store = new BigBlockStore(EMPTY_BIG_BLOCK_ARRAY);
if(blocks.length == 0) {
_bigBigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
} else {
_bigBigBlockSize = blocks[0].getBigBlockSize();
}
_big_store = new BigBlockStore(_bigBigBlockSize, EMPTY_BIG_BLOCK_ARRAY);
_property = new DocumentProperty(name, _size);
_small_store = new SmallBlockStore(blocks);
_small_store = new SmallBlockStore(_bigBigBlockSize, blocks);
_property.setDocument(this);
}
@ -107,18 +126,22 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param blocks the small blocks making up the POIFSDocument
* @param length the actual length of the POIFSDocument
*/
public POIFSDocument(String name, ListManagedBlock[] blocks, int length) throws IOException {
public POIFSDocument(String name, POIFSBigBlockSize bigBlockSize, ListManagedBlock[] blocks, int length) throws IOException {
_size = length;
_bigBigBlockSize = bigBlockSize;
_property = new DocumentProperty(name, _size);
_property.setDocument(this);
if (Property.isSmall(_size)) {
_big_store = new BigBlockStore(EMPTY_BIG_BLOCK_ARRAY);
_small_store = new SmallBlockStore(convertRawBlocksToSmallBlocks(blocks));
_big_store = new BigBlockStore(bigBlockSize,EMPTY_BIG_BLOCK_ARRAY);
_small_store = new SmallBlockStore(bigBlockSize,convertRawBlocksToSmallBlocks(blocks));
} else {
_big_store = new BigBlockStore(convertRawBlocksToBigBlocks(blocks));
_small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY);
_big_store = new BigBlockStore(bigBlockSize,convertRawBlocksToBigBlocks(blocks));
_small_store = new SmallBlockStore(bigBlockSize,EMPTY_SMALL_BLOCK_ARRAY);
}
}
public POIFSDocument(String name, ListManagedBlock[] blocks, int length) throws IOException {
this(name, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, blocks, length);
}
/**
* Constructor
@ -126,12 +149,13 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param name the name of the POIFSDocument
* @param stream the InputStream we read data from
*/
public POIFSDocument(String name, InputStream stream) throws IOException {
public POIFSDocument(String name, POIFSBigBlockSize bigBlockSize, InputStream stream) throws IOException {
List<DocumentBlock> blocks = new ArrayList<DocumentBlock>();
_size = 0;
_bigBigBlockSize = bigBlockSize;
while (true) {
DocumentBlock block = new DocumentBlock(stream);
DocumentBlock block = new DocumentBlock(stream, bigBlockSize);
int blockSize = block.size();
if (blockSize > 0) {
@ -144,16 +168,19 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
}
DocumentBlock[] bigBlocks = blocks.toArray(new DocumentBlock[blocks.size()]);
_big_store = new BigBlockStore(bigBlocks);
_big_store = new BigBlockStore(bigBlockSize,bigBlocks);
_property = new DocumentProperty(name, _size);
_property.setDocument(this);
if (_property.shouldUseSmallBlocks()) {
_small_store = new SmallBlockStore(SmallDocumentBlock.convert(bigBlocks, _size));
_big_store = new BigBlockStore(new DocumentBlock[0]);
_small_store = new SmallBlockStore(bigBlockSize,SmallDocumentBlock.convert(bigBlockSize,bigBlocks, _size));
_big_store = new BigBlockStore(bigBlockSize,new DocumentBlock[0]);
} else {
_small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY);
_small_store = new SmallBlockStore(bigBlockSize,EMPTY_SMALL_BLOCK_ARRAY);
}
}
public POIFSDocument(String name, InputStream stream) throws IOException {
this(name, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, stream);
}
/**
* Constructor
@ -163,18 +190,22 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param path the path of the POIFSDocument
* @param writer the writer who will eventually write the document contents
*/
public POIFSDocument(String name, int size, POIFSDocumentPath path, POIFSWriterListener writer) {
public POIFSDocument(String name, int size, POIFSBigBlockSize bigBlockSize, POIFSDocumentPath path, POIFSWriterListener writer) {
_size = size;
_bigBigBlockSize = bigBlockSize;
_property = new DocumentProperty(name, _size);
_property.setDocument(this);
if (_property.shouldUseSmallBlocks()) {
_small_store = new SmallBlockStore(path, name, size, writer);
_big_store = new BigBlockStore(EMPTY_BIG_BLOCK_ARRAY);
_small_store = new SmallBlockStore(_bigBigBlockSize, path, name, size, writer);
_big_store = new BigBlockStore(_bigBigBlockSize, EMPTY_BIG_BLOCK_ARRAY);
} else {
_small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY);
_big_store = new BigBlockStore(path, name, size, writer);
_small_store = new SmallBlockStore(_bigBigBlockSize, EMPTY_SMALL_BLOCK_ARRAY);
_big_store = new BigBlockStore(_bigBigBlockSize, path, name, size, writer);
}
}
public POIFSDocument(String name, int size, POIFSDocumentPath path, POIFSWriterListener writer) {
this(name, size, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, path, writer);
}
/**
* @return array of SmallDocumentBlocks; may be empty, cannot be null
@ -381,13 +412,15 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
private final String _name;
private final int _size;
private final POIFSWriterListener _writer;
private final POIFSBigBlockSize _bigBlockSize;
/**
* Constructor
*
* @param blocks blocks to construct the store from
*/
SmallBlockStore(SmallDocumentBlock[] blocks) {
SmallBlockStore(POIFSBigBlockSize bigBlockSize, SmallDocumentBlock[] blocks) {
_bigBlockSize = bigBlockSize;
_smallBlocks = blocks.clone();
this._path = null;
this._name = null;
@ -403,7 +436,9 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param size length of the document
* @param writer the object that will eventually write the document
*/
SmallBlockStore(POIFSDocumentPath path, String name, int size, POIFSWriterListener writer) {
SmallBlockStore(POIFSBigBlockSize bigBlockSize, POIFSDocumentPath path,
String name, int size, POIFSWriterListener writer) {
_bigBlockSize = bigBlockSize;
_smallBlocks = new SmallDocumentBlock[0];
this._path = path;
this._name = name;
@ -427,7 +462,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
DocumentOutputStream dstream = new DocumentOutputStream(stream, _size);
_writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, _path, _name, _size));
_smallBlocks = SmallDocumentBlock.convert(stream.toByteArray(), _size);
_smallBlocks = SmallDocumentBlock.convert(_bigBlockSize, stream.toByteArray(), _size);
}
return _smallBlocks;
}
@ -439,13 +474,15 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
private final String _name;
private final int _size;
private final POIFSWriterListener _writer;
private final POIFSBigBlockSize _bigBlockSize;
/**
* Constructor
*
* @param blocks the blocks making up the store
*/
BigBlockStore(DocumentBlock[] blocks) {
BigBlockStore(POIFSBigBlockSize bigBlockSize, DocumentBlock[] blocks) {
_bigBlockSize = bigBlockSize;
bigBlocks = blocks.clone();
_path = null;
_name = null;
@ -461,7 +498,9 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
* @param size length of the document
* @param writer the object that will eventually write the document
*/
BigBlockStore(POIFSDocumentPath path, String name, int size, POIFSWriterListener writer) {
BigBlockStore(POIFSBigBlockSize bigBlockSize, POIFSDocumentPath path,
String name, int size, POIFSWriterListener writer) {
_bigBlockSize = bigBlockSize;
bigBlocks = new DocumentBlock[0];
_path = path;
_name = name;
@ -485,7 +524,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
DocumentOutputStream dstream = new DocumentOutputStream(stream, _size);
_writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, _path, _name, _size));
bigBlocks = DocumentBlock.convert(stream.toByteArray(), _size);
bigBlocks = DocumentBlock.convert(_bigBlockSize, stream.toByteArray(), _size);
}
return bigBlocks;
}
@ -501,7 +540,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
DocumentOutputStream dstream = new DocumentOutputStream(stream, _size);
_writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, _path, _name, _size));
dstream.writeFiller(countBlocks() * POIFSConstants.BIG_BLOCK_SIZE,
dstream.writeFiller(countBlocks() * _bigBlockSize.getBigBlockSize(),
DocumentBlock.getFillByte());
} else {
for (int k = 0; k < bigBlocks.length; k++) {
@ -520,8 +559,8 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView
if (_writer == null) {
return bigBlocks.length;
}
return (_size + POIFSConstants.BIG_BLOCK_SIZE - 1)
/ POIFSConstants.BIG_BLOCK_SIZE;
return (_size + _bigBlockSize.getBigBlockSize() - 1)
/ _bigBlockSize.getBigBlockSize();
}
return 0;
}

View File

@ -31,6 +31,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.dev.POIFSViewable;
import org.apache.poi.poifs.property.DirectoryProperty;
@ -97,14 +98,15 @@ public class POIFSFileSystem
* What big block size the file uses. Most files
* use 512 bytes, but a few use 4096
*/
private int bigBlockSize = POIFSConstants.BIG_BLOCK_SIZE;
private POIFSBigBlockSize bigBlockSize =
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
/**
* Constructor, intended for writing
*/
public POIFSFileSystem()
{
_property_table = new PropertyTable();
_property_table = new PropertyTable(bigBlockSize);
_documents = new ArrayList();
_root = null;
}
@ -161,7 +163,8 @@ public class POIFSFileSystem
// set up the block allocation table (necessary for the
// data_blocks to be manageable
new BlockAllocationTableReader(header_block_reader.getBATCount(),
new BlockAllocationTableReader(header_block_reader.getBigBlockSize(),
header_block_reader.getBATCount(),
header_block_reader.getBATArray(),
header_block_reader.getXBATCount(),
header_block_reader.getXBATIndex(),
@ -169,13 +172,14 @@ public class POIFSFileSystem
// get property table from the document
PropertyTable properties =
new PropertyTable(header_block_reader.getPropertyStart(),
new PropertyTable(bigBlockSize,
header_block_reader.getPropertyStart(),
data_blocks);
// init documents
processProperties(
SmallBlockTableReader.getSmallDocumentBlocks(
data_blocks, properties.getRoot(),
bigBlockSize, data_blocks, properties.getRoot(),
header_block_reader.getSBATStart()
),
data_blocks,
@ -315,11 +319,11 @@ public class POIFSFileSystem
// create the small block store, and the SBAT
SmallBlockTableWriter sbtw =
new SmallBlockTableWriter(_documents, _property_table.getRoot());
new SmallBlockTableWriter(bigBlockSize, _documents, _property_table.getRoot());
// create the block allocation table
BlockAllocationTableWriter bat =
new BlockAllocationTableWriter();
new BlockAllocationTableWriter(bigBlockSize);
// create a list of BATManaged objects: the documents plus the
// property table and the small block table
@ -357,7 +361,7 @@ public class POIFSFileSystem
int batStartBlock = bat.createBlocks();
// get the extended block allocation table blocks
HeaderBlockWriter header_block_writer = new HeaderBlockWriter();
HeaderBlockWriter header_block_writer = new HeaderBlockWriter(bigBlockSize);
BATBlock[] xbat_blocks =
header_block_writer.setBATBlocks(bat.countBlocks(),
batStartBlock);
@ -612,7 +616,13 @@ public class POIFSFileSystem
* @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
*/
public int getBigBlockSize() {
return bigBlockSize;
return bigBlockSize.getBigBlockSize();
}
/**
* @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
*/
public POIFSBigBlockSize getBigBlockSizeDetails() {
return bigBlockSize;
}
/* ********** END begin implementation of POIFSViewable ********** */

View File

@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.BATManaged;
import org.apache.poi.poifs.storage.BlockWritable;
@ -37,12 +38,14 @@ import org.apache.poi.poifs.storage.RawDataBlockList;
* @author Marc Johnson (mjohnson at apache dot org)
*/
public final class PropertyTable implements BATManaged, BlockWritable {
private int _start_block;
private List<Property> _properties;
private BlockWritable[] _blocks;
private POIFSBigBlockSize _bigBigBlockSize;
private int _start_block;
private List<Property> _properties;
private BlockWritable[] _blocks;
public PropertyTable()
public PropertyTable(POIFSBigBlockSize bigBlockSize)
{
_bigBigBlockSize = bigBlockSize;
_start_block = POIFSConstants.END_OF_CHAIN;
_properties = new ArrayList<Property>();
addProperty(new RootProperty());
@ -60,10 +63,12 @@ public final class PropertyTable implements BATManaged, BlockWritable {
* @exception IOException if anything goes wrong (which should be
* a result of the input being NFG)
*/
public PropertyTable(final int startBlock,
public PropertyTable(final POIFSBigBlockSize bigBlockSize,
final int startBlock,
final RawDataBlockList blockList)
throws IOException
{
_bigBigBlockSize = bigBlockSize;
_start_block = POIFSConstants.END_OF_CHAIN;
_blocks = null;
_properties =
@ -118,7 +123,7 @@ public final class PropertyTable implements BATManaged, BlockWritable {
}
// allocate the blocks for the property table
_blocks = PropertyBlock.createPropertyBlockArray(_properties);
_blocks = PropertyBlock.createPropertyBlockArray(_bigBigBlockSize, _properties);
// prepare each property for writing
for (int k = 0; k < properties.length; k++)

View File

@ -22,6 +22,7 @@ import java.io.OutputStream;
import java.util.Arrays;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IntegerField;
import org.apache.poi.util.LittleEndianConsts;
@ -33,12 +34,6 @@ import org.apache.poi.util.LittleEndianConsts;
* @author Marc Johnson (mjohnson at apache dot org)
*/
public final class BATBlock extends BigBlock {
private static final int _entries_per_block =
POIFSConstants.BIG_BLOCK_SIZE / LittleEndianConsts.INT_SIZE;
private static final int _entries_per_xbat_block = _entries_per_block
- 1;
private static final int _xbat_chain_offset =
_entries_per_xbat_block * LittleEndianConsts.INT_SIZE;
private static final byte _default_value = ( byte ) 0xFF;
private IntegerField[] _fields;
private byte[] _data;
@ -47,9 +42,13 @@ public final class BATBlock extends BigBlock {
* Create a single instance initialized with default values
*/
private BATBlock()
private BATBlock(POIFSBigBlockSize bigBlockSize)
{
_data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
super(bigBlockSize);
int _entries_per_block = bigBlockSize.getBATEntriesPerBlock();
_data = new byte[ bigBlockSize.getBigBlockSize() ];
Arrays.fill(_data, _default_value);
_fields = new IntegerField[ _entries_per_block ];
int offset = 0;
@ -70,16 +69,17 @@ public final class BATBlock extends BigBlock {
* @return the newly created array of BATBlocks
*/
public static BATBlock [] createBATBlocks(final int [] entries)
public static BATBlock [] createBATBlocks(final POIFSBigBlockSize bigBlockSize, final int [] entries)
{
int block_count = calculateStorageRequirements(entries.length);
int block_count = calculateStorageRequirements(bigBlockSize, entries.length);
BATBlock[] blocks = new BATBlock[ block_count ];
int index = 0;
int remaining = entries.length;
int _entries_per_block = bigBlockSize.getBATEntriesPerBlock();
for (int j = 0; j < entries.length; j += _entries_per_block)
{
blocks[ index++ ] = new BATBlock(entries, j,
blocks[ index++ ] = new BATBlock(bigBlockSize, entries, j,
(remaining > _entries_per_block)
? j + _entries_per_block
: entries.length);
@ -98,21 +98,23 @@ public final class BATBlock extends BigBlock {
* @return the newly created array of BATBlocks
*/
public static BATBlock [] createXBATBlocks(final int [] entries,
public static BATBlock [] createXBATBlocks(final POIFSBigBlockSize bigBlockSize,
final int [] entries,
final int startBlock)
{
int block_count =
calculateXBATStorageRequirements(entries.length);
calculateXBATStorageRequirements(bigBlockSize, entries.length);
BATBlock[] blocks = new BATBlock[ block_count ];
int index = 0;
int remaining = entries.length;
int _entries_per_xbat_block = bigBlockSize.getXBATEntriesPerBlock();
if (block_count != 0)
{
for (int j = 0; j < entries.length; j += _entries_per_xbat_block)
{
blocks[ index++ ] =
new BATBlock(entries, j,
new BATBlock(bigBlockSize, entries, j,
(remaining > _entries_per_xbat_block)
? j + _entries_per_xbat_block
: entries.length);
@ -120,9 +122,9 @@ public final class BATBlock extends BigBlock {
}
for (index = 0; index < blocks.length - 1; index++)
{
blocks[ index ].setXBATChain(startBlock + index + 1);
blocks[ index ].setXBATChain(bigBlockSize, startBlock + index + 1);
}
blocks[ index ].setXBATChain(POIFSConstants.END_OF_CHAIN);
blocks[ index ].setXBATChain(bigBlockSize, POIFSConstants.END_OF_CHAIN);
}
return blocks;
}
@ -136,8 +138,9 @@ public final class BATBlock extends BigBlock {
* @return the number of BATBlocks needed
*/
public static int calculateStorageRequirements(final int entryCount)
public static int calculateStorageRequirements(final POIFSBigBlockSize bigBlockSize, final int entryCount)
{
int _entries_per_block = bigBlockSize.getBATEntriesPerBlock();
return (entryCount + _entries_per_block - 1) / _entries_per_block;
}
@ -150,41 +153,16 @@ public final class BATBlock extends BigBlock {
* @return the number of XBATBlocks needed
*/
public static int calculateXBATStorageRequirements(final int entryCount)
public static int calculateXBATStorageRequirements(final POIFSBigBlockSize bigBlockSize, final int entryCount)
{
int _entries_per_xbat_block = bigBlockSize.getXBATEntriesPerBlock();
return (entryCount + _entries_per_xbat_block - 1)
/ _entries_per_xbat_block;
}
/**
* @return number of entries per block
*/
public static final int entriesPerBlock()
{
return _entries_per_block;
}
/**
* @return number of entries per XBAT block
*/
public static final int entriesPerXBATBlock()
{
return _entries_per_xbat_block;
}
/**
* @return offset of chain index of XBAT block
*/
public static final int getXBATChainOffset()
{
return _xbat_chain_offset;
}
private void setXBATChain(int chainIndex)
private void setXBATChain(final POIFSBigBlockSize bigBlockSize, int chainIndex)
{
int _entries_per_xbat_block = bigBlockSize.getXBATEntriesPerBlock();
_fields[ _entries_per_xbat_block ].set(chainIndex, _data);
}
@ -199,10 +177,10 @@ public final class BATBlock extends BigBlock {
* k, start_index <= k < end_index)
*/
private BATBlock(final int [] entries, final int start_index,
final int end_index)
private BATBlock(POIFSBigBlockSize bigBlockSize, final int [] entries,
final int start_index, final int end_index)
{
this();
this(bigBlockSize);
for (int k = start_index; k < end_index; k++)
{
_fields[ k - start_index ].set(entries[ k ], _data);

View File

@ -33,9 +33,21 @@ package org.apache.poi.poifs.storage;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
abstract class BigBlock
implements BlockWritable
{
/**
* Either 512 bytes ({@link POIFSConstants#SMALLER_BIG_BLOCK_SIZE})
* or 4096 bytes ({@link POIFSConstants#LARGER_BIG_BLOCK_SIZE})
*/
protected POIFSBigBlockSize bigBlockSize;
protected BigBlock(POIFSBigBlockSize bigBlockSize) {
this.bigBlockSize = bigBlockSize;
}
/**
* Default implementation of write for extending classes that

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import java.util.*;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IntList;
import org.apache.poi.util.LittleEndian;
@ -56,6 +57,7 @@ public final class BlockAllocationTableReader {
*/
private static final int MAX_BLOCK_COUNT = 65535;
private final IntList _entries;
private POIFSBigBlockSize bigBlockSize;
/**
* create a BlockAllocationTableReader for an existing filesystem. Side
@ -75,9 +77,10 @@ public final class BlockAllocationTableReader {
* @exception IOException if, in trying to create the table, we
* encounter logic errors
*/
public BlockAllocationTableReader(int block_count, int [] block_array,
public BlockAllocationTableReader(POIFSBigBlockSize bigBlockSize, int block_count, int [] block_array,
int xbat_count, int xbat_index, BlockList raw_block_list) throws IOException {
this();
this(bigBlockSize);
if (block_count <= 0) {
throw new IOException(
"Illegal block count; minimum count is 1, got " + block_count
@ -128,8 +131,8 @@ public final class BlockAllocationTableReader {
"BAT count exceeds limit, yet XBAT index indicates no valid entries");
}
int chain_index = xbat_index;
int max_entries_per_block = BATBlock.entriesPerXBATBlock();
int chain_index_offset = BATBlock.getXBATChainOffset();
int max_entries_per_block = bigBlockSize.getXBATEntriesPerBlock();
int chain_index_offset = bigBlockSize.getNextXBATChainOffset();
// Each XBAT block contains either:
// (maximum number of sector indexes) + index of next XBAT
@ -173,13 +176,14 @@ public final class BlockAllocationTableReader {
*
* @exception IOException
*/
BlockAllocationTableReader(ListManagedBlock[] blocks, BlockList raw_block_list)
BlockAllocationTableReader(POIFSBigBlockSize bigBlockSize, ListManagedBlock[] blocks, BlockList raw_block_list)
throws IOException {
this();
this(bigBlockSize);
setEntries(blocks, raw_block_list);
}
BlockAllocationTableReader() {
BlockAllocationTableReader(POIFSBigBlockSize bigBlockSize) {
this.bigBlockSize = bigBlockSize;
_entries = new IntList();
}
@ -279,7 +283,7 @@ public final class BlockAllocationTableReader {
* blocks will be eliminated from the list
*/
private void setEntries(ListManagedBlock[] blocks, BlockList raw_blocks) throws IOException {
int limit = BATBlock.entriesPerBlock();
int limit = bigBlockSize.getBATEntriesPerBlock();
for (int block_index = 0; block_index < blocks.length; block_index++)
{

View File

@ -20,6 +20,7 @@ package org.apache.poi.poifs.storage;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.BATManaged;
import org.apache.poi.util.IntList;
@ -43,15 +44,17 @@ public final class BlockAllocationTableWriter implements BlockWritable, BATManag
private IntList _entries;
private BATBlock[] _blocks;
private int _start_block;
private POIFSBigBlockSize _bigBlockSize;
/**
* create a BlockAllocationTableWriter
*/
public BlockAllocationTableWriter()
public BlockAllocationTableWriter(POIFSBigBlockSize bigBlockSize)
{
_start_block = POIFSConstants.END_OF_CHAIN;
_entries = new IntList();
_blocks = new BATBlock[ 0 ];
_bigBlockSize = bigBlockSize;
_start_block = POIFSConstants.END_OF_CHAIN;
_entries = new IntList();
_blocks = new BATBlock[ 0 ];
}
/**
@ -67,12 +70,13 @@ public final class BlockAllocationTableWriter implements BlockWritable, BATManag
while (true)
{
int calculated_bat_blocks =
BATBlock.calculateStorageRequirements(bat_blocks
BATBlock.calculateStorageRequirements(_bigBlockSize,
bat_blocks
+ xbat_blocks
+ _entries.size());
int calculated_xbat_blocks =
HeaderBlockWriter
.calculateXBATStorageRequirements(calculated_bat_blocks);
HeaderBlockWriter.calculateXBATStorageRequirements(
_bigBlockSize, calculated_bat_blocks);
if ((bat_blocks == calculated_bat_blocks)
&& (xbat_blocks == calculated_xbat_blocks))
@ -131,7 +135,7 @@ public final class BlockAllocationTableWriter implements BlockWritable, BATManag
*/
void simpleCreateBlocks()
{
_blocks = BATBlock.createBATBlocks(_entries.toArray());
_blocks = BATBlock.createBATBlocks(_bigBlockSize, _entries.toArray());
}
/**

View File

@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IOUtils;
@ -50,6 +51,11 @@ public final class DocumentBlock extends BigBlock {
public DocumentBlock(final RawDataBlock block)
throws IOException
{
super(
block.getBigBlockSize() == POIFSConstants.SMALLER_BIG_BLOCK_SIZE ?
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS :
POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS
);
_data = block.getData();
_bytes_read = _data.length;
}
@ -62,10 +68,10 @@ public final class DocumentBlock extends BigBlock {
* @exception IOException
*/
public DocumentBlock(final InputStream stream)
public DocumentBlock(final InputStream stream, POIFSBigBlockSize bigBlockSize)
throws IOException
{
this();
this(bigBlockSize);
int count = IOUtils.readFully(stream, _data);
_bytes_read = (count == -1) ? 0
@ -76,9 +82,10 @@ public final class DocumentBlock extends BigBlock {
* Create a single instance initialized with default values
*/
private DocumentBlock()
private DocumentBlock(POIFSBigBlockSize bigBlockSize)
{
_data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
super(bigBlockSize);
_data = new byte[ bigBlockSize.getBigBlockSize() ];
Arrays.fill(_data, _default_value);
}
@ -101,7 +108,7 @@ public final class DocumentBlock extends BigBlock {
public boolean partiallyRead()
{
return _bytes_read != POIFSConstants.BIG_BLOCK_SIZE;
return _bytes_read != bigBlockSize.getBigBlockSize();
}
/**
@ -124,26 +131,27 @@ public final class DocumentBlock extends BigBlock {
* input array
*/
public static DocumentBlock [] convert(final byte [] array,
public static DocumentBlock [] convert(final POIFSBigBlockSize bigBlockSize,
final byte [] array,
final int size)
{
DocumentBlock[] rval =
new DocumentBlock[ (size + POIFSConstants.BIG_BLOCK_SIZE - 1) / POIFSConstants.BIG_BLOCK_SIZE ];
new DocumentBlock[ (size + bigBlockSize.getBigBlockSize() - 1) / bigBlockSize.getBigBlockSize() ];
int offset = 0;
for (int k = 0; k < rval.length; k++)
{
rval[ k ] = new DocumentBlock();
rval[ k ] = new DocumentBlock(bigBlockSize);
if (offset < array.length)
{
int length = Math.min(POIFSConstants.BIG_BLOCK_SIZE,
int length = Math.min(bigBlockSize.getBigBlockSize(),
array.length - offset);
System.arraycopy(array, offset, rval[ k ]._data, 0, length);
if (length != POIFSConstants.BIG_BLOCK_SIZE)
if (length != bigBlockSize.getBigBlockSize())
{
Arrays.fill(rval[ k ]._data, length,
POIFSConstants.BIG_BLOCK_SIZE,
bigBlockSize.getBigBlockSize(),
_default_value);
}
}
@ -151,7 +159,7 @@ public final class DocumentBlock extends BigBlock {
{
Arrays.fill(rval[ k ]._data, _default_value);
}
offset += POIFSConstants.BIG_BLOCK_SIZE;
offset += bigBlockSize.getBigBlockSize();
}
return rval;
}

View File

@ -30,8 +30,8 @@ public interface HeaderBlockConstants
public static final long _signature = 0xE11AB1A1E011CFD0L;
public static final int _bat_array_offset = 0x4c;
public static final int _max_bats_in_header =
(POIFSConstants.BIG_BLOCK_SIZE - _bat_array_offset)
/ LittleEndianConsts.INT_SIZE;
(POIFSConstants.SMALLER_BIG_BLOCK_SIZE - _bat_array_offset)
/ LittleEndianConsts.INT_SIZE; // If 4k blocks, rest is blank
// Note - in Microsoft terms:
// BAT ~= FAT

View File

@ -31,6 +31,7 @@ import static org.apache.poi.poifs.storage.HeaderBlockConstants._xbat_start_offs
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.util.HexDump;
@ -48,7 +49,7 @@ public final class HeaderBlockReader {
* What big block size the file uses. Most files
* use 512 bytes, but a few use 4096
*/
private final int bigBlockSize;
private final POIFSBigBlockSize bigBlockSize;
/**
* number of big block allocation table blocks (int).
@ -130,20 +131,20 @@ public final class HeaderBlockReader {
// Figure out our block size
switch (blockStart[30]) {
case 12:
bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE; break;
bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS; break;
case 9:
bigBlockSize = POIFSConstants.BIG_BLOCK_SIZE; break;
bigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS; break;
default:
throw new IOException("Unsupported blocksize (2^"
+ blockStart[30] + "). Expected 2^9 or 2^12.");
}
_data = new byte[ bigBlockSize ];
_data = new byte[ bigBlockSize.getBigBlockSize() ];
System.arraycopy(blockStart, 0, _data, 0, blockStart.length);
// Now we can read the rest of our header
int byte_count = IOUtils.readFully(stream, _data, blockStart.length, _data.length - blockStart.length);
if (byte_count+bsCount != bigBlockSize) {
throw alertShortRead(byte_count, bigBlockSize);
if (byte_count+bsCount != bigBlockSize.getBigBlockSize()) {
throw alertShortRead(byte_count, bigBlockSize.getBigBlockSize());
}
_bat_count = getInt(_bat_count_offset, _data);
@ -237,7 +238,7 @@ public final class HeaderBlockReader {
/**
* @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
*/
public int getBigBlockSize() {
public POIFSBigBlockSize getBigBlockSize() {
return bigBlockSize;
}
}

View File

@ -23,6 +23,7 @@ import java.io.*;
import java.util.*;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IntegerField;
import org.apache.poi.util.LittleEndianConsts;
@ -64,9 +65,11 @@ public class HeaderBlockWriter
* Create a single instance initialized with default values
*/
public HeaderBlockWriter()
public HeaderBlockWriter(POIFSBigBlockSize bigBlockSize)
{
_data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
super(bigBlockSize);
_data = new byte[ bigBlockSize.getBigBlockSize() ];
Arrays.fill(_data, _default_value);
new LongField(_signature_offset, _signature, _data);
new IntegerField(0x08, 0, _data);
@ -76,7 +79,15 @@ public class HeaderBlockWriter
new ShortField(0x18, ( short ) 0x3b, _data);
new ShortField(0x1a, ( short ) 0x3, _data);
new ShortField(0x1c, ( short ) -2, _data);
new ShortField(0x1e, ( short ) 0x9, _data);
new ShortField(0x1e, bigBlockSize.getHeaderValue(), _data);
if(bigBlockSize.getBigBlockSize() == POIFSConstants.LARGER_BIG_BLOCK_SIZE) {
// Need to fill the extra header size with zeros
for(int i=POIFSConstants.SMALLER_BIG_BLOCK_SIZE; i<_data.length; i++) {
_data[i] = 0;
}
}
new IntegerField(0x20, 0x6, _data);
new IntegerField(0x24, 0, _data);
new IntegerField(0x28, 0, _data);
@ -131,13 +142,13 @@ public class HeaderBlockWriter
excess_block_array[ j ] = startBlock + j
+ _max_bats_in_header;
}
rvalue = BATBlock.createXBATBlocks(excess_block_array,
rvalue = BATBlock.createXBATBlocks(bigBlockSize, excess_block_array,
startBlock + blockCount);
_xbat_start.set(startBlock + blockCount, _data);
}
else
{
rvalue = BATBlock.createXBATBlocks(new int[ 0 ], 0);
rvalue = BATBlock.createXBATBlocks(bigBlockSize, new int[ 0 ], 0);
_xbat_start.set(POIFSConstants.END_OF_CHAIN, _data);
}
_xbat_count.set(rvalue.length, _data);
@ -188,11 +199,11 @@ public class HeaderBlockWriter
* @return number of XBAT blocks needed
*/
static int calculateXBATStorageRequirements(final int blockCount)
static int calculateXBATStorageRequirements(POIFSBigBlockSize bigBlockSize, final int blockCount)
{
return (blockCount > _max_bats_in_header)
? BATBlock.calculateXBATStorageRequirements(blockCount
- _max_bats_in_header)
? BATBlock.calculateXBATStorageRequirements(
bigBlockSize, blockCount - _max_bats_in_header)
: 0;
}

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.property.Property;
@ -30,8 +31,6 @@ import org.apache.poi.poifs.property.Property;
* @author Marc Johnson (mjohnson at apache dot org)
*/
public final class PropertyBlock extends BigBlock {
private static final int _properties_per_block =
POIFSConstants.BIG_BLOCK_SIZE / POIFSConstants.PROPERTY_SIZE;
private Property[] _properties;
/**
@ -41,10 +40,12 @@ public final class PropertyBlock extends BigBlock {
* @param offset the offset into the properties array
*/
private PropertyBlock(final Property [] properties, final int offset)
private PropertyBlock(final POIFSBigBlockSize bigBlockSize, final Property [] properties, final int offset)
{
_properties = new Property[ _properties_per_block ];
for (int j = 0; j < _properties_per_block; j++)
super(bigBlockSize);
_properties = new Property[ bigBlockSize.getPropertiesPerBlock() ];
for (int j = 0; j < _properties.length; j++)
{
_properties[ j ] = properties[ j + offset ];
}
@ -62,8 +63,9 @@ public final class PropertyBlock extends BigBlock {
*/
public static BlockWritable [] createPropertyBlockArray(
final List properties)
final POIFSBigBlockSize bigBlockSize, final List properties)
{
int _properties_per_block = bigBlockSize.getPropertiesPerBlock();
int block_count =
(properties.size() + _properties_per_block - 1)
/ _properties_per_block;
@ -93,7 +95,7 @@ public final class PropertyBlock extends BigBlock {
for (int j = 0; j < block_count; j++)
{
rvalue[ j ] = new PropertyBlock(to_be_written,
rvalue[ j ] = new PropertyBlock(bigBlockSize, to_be_written,
j * _properties_per_block);
}
return rvalue;
@ -114,6 +116,7 @@ public final class PropertyBlock extends BigBlock {
void writeData(final OutputStream stream)
throws IOException
{
int _properties_per_block = bigBlockSize.getPropertiesPerBlock();
for (int j = 0; j < _properties_per_block; j++)
{
_properties[ j ].writeData(stream);

View File

@ -51,7 +51,7 @@ public class RawDataBlock
*/
public RawDataBlock(final InputStream stream)
throws IOException {
this(stream, POIFSConstants.BIG_BLOCK_SIZE);
this(stream, POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
}
/**
* Constructor RawDataBlock
@ -134,6 +134,13 @@ public class RawDataBlock
}
return _data;
}
/**
* What's the big block size?
*/
public int getBigBlockSize() {
return _data.length;
}
/* ********** END implementation of ListManagedBlock ********** */
} // end public class RawDataBlock

View File

@ -23,6 +23,8 @@ import java.io.*;
import java.util.*;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
/**
* A list of RawDataBlocks instances, and methods to manage the list
*
@ -43,14 +45,14 @@ public class RawDataBlockList
* block is read
*/
public RawDataBlockList(final InputStream stream, int bigBlockSize)
public RawDataBlockList(final InputStream stream, POIFSBigBlockSize bigBlockSize)
throws IOException
{
List blocks = new ArrayList();
List<RawDataBlock> blocks = new ArrayList<RawDataBlock>();
while (true)
{
RawDataBlock block = new RawDataBlock(stream, bigBlockSize);
RawDataBlock block = new RawDataBlock(stream, bigBlockSize.getBigBlockSize());
// If there was data, add the block to the list
if(block.hasData()) {
@ -62,7 +64,7 @@ public class RawDataBlockList
break;
}
}
setBlocks(( RawDataBlock [] ) blocks.toArray(new RawDataBlock[ 0 ]));
setBlocks( blocks.toArray(new RawDataBlock[ blocks.size() ]) );
}
} // end public class RawDataBlockList

View File

@ -19,6 +19,7 @@ package org.apache.poi.poifs.storage;
import java.io.IOException;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.property.RootProperty;
/**
@ -43,15 +44,22 @@ public final class SmallBlockTableReader {
* @exception IOException
*/
public static BlockList getSmallDocumentBlocks(
final POIFSBigBlockSize bigBlockSize,
final RawDataBlockList blockList, final RootProperty root,
final int sbatStart)
throws IOException
{
BlockList list =
new SmallDocumentBlockList(SmallDocumentBlock
.extract(blockList.fetchBlocks(root.getStartBlock(), -1)));
// Fetch the blocks which hold the Small Blocks stream
ListManagedBlock [] smallBlockBlocks =
blockList.fetchBlocks(root.getStartBlock(), -1);
// Turn that into a list
BlockList list =new SmallDocumentBlockList(
SmallDocumentBlock.extract(bigBlockSize, smallBlockBlocks));
new BlockAllocationTableReader(blockList.fetchBlocks(sbatStart, -1),
// Process
new BlockAllocationTableReader(bigBlockSize,
blockList.fetchBlocks(sbatStart, -1),
list);
return list;
}

View File

@ -19,6 +19,7 @@
package org.apache.poi.poifs.storage;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.BATManaged;
import org.apache.poi.poifs.filesystem.POIFSDocument;
@ -50,10 +51,11 @@ public class SmallBlockTableWriter
* @param root the Filesystem's root property
*/
public SmallBlockTableWriter(final List documents,
public SmallBlockTableWriter(final POIFSBigBlockSize bigBlockSize,
final List documents,
final RootProperty root)
{
_sbat = new BlockAllocationTableWriter();
_sbat = new BlockAllocationTableWriter(bigBlockSize);
_small_blocks = new ArrayList();
_root = root;
Iterator iter = documents.iterator();
@ -76,7 +78,7 @@ public class SmallBlockTableWriter
}
_sbat.simpleCreateBlocks();
_root.setSize(_small_blocks.size());
_big_block_count = SmallDocumentBlock.fill(_small_blocks);
_big_block_count = SmallDocumentBlock.fill(bigBlockSize,_small_blocks);
}
/**

View File

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
/**
@ -40,19 +41,26 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
private static final int _block_size = 1 << BLOCK_SHIFT;
private static final int BLOCK_MASK = _block_size-1;
private static final int _blocks_per_big_block =
POIFSConstants.BIG_BLOCK_SIZE / _block_size;
private final int _blocks_per_big_block;
private final POIFSBigBlockSize _bigBlockSize;
private SmallDocumentBlock(final byte [] data, final int index)
private SmallDocumentBlock(final POIFSBigBlockSize bigBlockSize, final byte [] data, final int index)
{
this();
this(bigBlockSize);
System.arraycopy(data, index * _block_size, _data, 0, _block_size);
}
private SmallDocumentBlock()
private SmallDocumentBlock(final POIFSBigBlockSize bigBlockSize)
{
_bigBlockSize = bigBlockSize;
_blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
_data = new byte[ _block_size ];
}
private static int getBlocksPerBigBlock(final POIFSBigBlockSize bigBlockSize)
{
return bigBlockSize.getBigBlockSize() / _block_size;
}
/**
* convert a single long array into an array of SmallDocumentBlock
@ -64,7 +72,8 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
* @return an array of SmallDocumentBlock instances, filled from
* the array
*/
public static SmallDocumentBlock [] convert(byte [] array,
public static SmallDocumentBlock [] convert(POIFSBigBlockSize bigBlockSize,
byte [] array,
int size)
{
SmallDocumentBlock[] rval =
@ -73,7 +82,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
for (int k = 0; k < rval.length; k++)
{
rval[ k ] = new SmallDocumentBlock();
rval[ k ] = new SmallDocumentBlock(bigBlockSize);
if (offset < array.length)
{
int length = Math.min(_block_size, array.length - offset);
@ -102,8 +111,10 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
*
* @return number of big blocks the list encompasses
*/
public static int fill(List blocks)
public static int fill(POIFSBigBlockSize bigBlockSize, List blocks)
{
int _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
int count = blocks.size();
int big_block_count = (count + _blocks_per_big_block - 1)
/ _blocks_per_big_block;
@ -111,7 +122,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
for (; count < full_count; count++)
{
blocks.add(makeEmptySmallDocumentBlock());
blocks.add(makeEmptySmallDocumentBlock(bigBlockSize));
}
return big_block_count;
}
@ -128,7 +139,8 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
* @exception ArrayIndexOutOfBoundsException if, somehow, the store
* contains less data than size indicates
*/
public static SmallDocumentBlock [] convert(BlockWritable [] store,
public static SmallDocumentBlock [] convert(POIFSBigBlockSize bigBlockSize,
BlockWritable [] store,
int size)
throws IOException, ArrayIndexOutOfBoundsException
{
@ -144,7 +156,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
for (int index = 0; index < rval.length; index++)
{
rval[ index ] = new SmallDocumentBlock(data, index);
rval[ index ] = new SmallDocumentBlock(bigBlockSize, data, index);
}
return rval;
}
@ -157,9 +169,11 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
*
* @return a List of SmallDocumentBlock's extracted from the input
*/
public static List extract(ListManagedBlock [] blocks)
public static List extract(POIFSBigBlockSize bigBlockSize, ListManagedBlock [] blocks)
throws IOException
{
int _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
List sdbs = new ArrayList();
for (int j = 0; j < blocks.length; j++)
@ -168,7 +182,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
for (int k = 0; k < _blocks_per_big_block; k++)
{
sdbs.add(new SmallDocumentBlock(data, k));
sdbs.add(new SmallDocumentBlock(bigBlockSize, data, k));
}
}
return sdbs;
@ -192,9 +206,9 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
return size * _block_size;
}
private static SmallDocumentBlock makeEmptySmallDocumentBlock()
private static SmallDocumentBlock makeEmptySmallDocumentBlock(POIFSBigBlockSize bigBlockSize)
{
SmallDocumentBlock block = new SmallDocumentBlock();
SmallDocumentBlock block = new SmallDocumentBlock(bigBlockSize);
Arrays.fill(block._data, _default_fill);
return block;
@ -230,4 +244,8 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
public byte [] getData() {
return _data;
}
public POIFSBigBlockSize getBigBlockSize() {
return _bigBlockSize;
}
}

View File

@ -40,7 +40,7 @@ public class SmallDocumentBlockList
public SmallDocumentBlockList(final List blocks)
{
setBlocks(( SmallDocumentBlock [] ) blocks
.toArray(new SmallDocumentBlock[ 0 ]));
.toArray(new SmallDocumentBlock[ blocks.size() ]));
}
} // end public class SmallDocumentBlockList

View File

@ -448,8 +448,8 @@ public final class HWPFDocument extends POIDocument
// determine the FileInformationBLock size
int fibSize = _fib.getSize();
fibSize += POIFSConstants.BIG_BLOCK_SIZE -
(fibSize % POIFSConstants.BIG_BLOCK_SIZE);
fibSize += POIFSConstants.SMALLER_BIG_BLOCK_SIZE -
(fibSize % POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
// preserve space for the FileInformationBlock because we will be writing
// it after we write everything else.

View File

@ -65,7 +65,7 @@ public final class CHPBinTable
GenericPropertyNode node = binTable.getProperty(x);
int pageNum = LittleEndian.getInt(node.getBytes());
int pageOffset = POIFSConstants.BIG_BLOCK_SIZE * pageNum;
int pageOffset = POIFSConstants.SMALLER_BIG_BLOCK_SIZE * pageNum;
CHPFormattedDiskPage cfkp = new CHPFormattedDiskPage(documentStream,
pageOffset, fcMin, tpt);
@ -187,16 +187,16 @@ public final class CHPBinTable
// each FKP must start on a 512 byte page.
int docOffset = docStream.getOffset();
int mod = docOffset % POIFSConstants.BIG_BLOCK_SIZE;
int mod = docOffset % POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
if (mod != 0)
{
byte[] padding = new byte[POIFSConstants.BIG_BLOCK_SIZE - mod];
byte[] padding = new byte[POIFSConstants.SMALLER_BIG_BLOCK_SIZE - mod];
docStream.write(padding);
}
// get the page number for the first fkp
docOffset = docStream.getOffset();
int pageNum = docOffset/POIFSConstants.BIG_BLOCK_SIZE;
int pageNum = docOffset/POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
// get the ending fc
int endingFc = ((PropertyNode)_textRuns.get(_textRuns.size() - 1)).getEnd();

View File

@ -58,7 +58,7 @@ public final class PAPBinTable
GenericPropertyNode node = binTable.getProperty(x);
int pageNum = LittleEndian.getInt(node.getBytes());
int pageOffset = POIFSConstants.BIG_BLOCK_SIZE * pageNum;
int pageOffset = POIFSConstants.SMALLER_BIG_BLOCK_SIZE * pageNum;
PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage(documentStream,
dataStream, pageOffset, fcMin, tpt);
@ -195,16 +195,16 @@ public final class PAPBinTable
// each FKP must start on a 512 byte page.
int docOffset = docStream.getOffset();
int mod = docOffset % POIFSConstants.BIG_BLOCK_SIZE;
int mod = docOffset % POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
if (mod != 0)
{
byte[] padding = new byte[POIFSConstants.BIG_BLOCK_SIZE - mod];
byte[] padding = new byte[POIFSConstants.SMALLER_BIG_BLOCK_SIZE - mod];
docStream.write(padding);
}
// get the page number for the first fkp
docOffset = docStream.getOffset();
int pageNum = docOffset/POIFSConstants.BIG_BLOCK_SIZE;
int pageNum = docOffset/POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
// get the ending fc
int endingFc = ((PropertyNode)_paragraphs.get(_paragraphs.size() - 1)).getEnd();

View File

@ -172,9 +172,9 @@ public final class TextPieceTable implements CharIndexTranslator {
PieceDescriptor pd = next.getPieceDescriptor();
int offset = docStream.getOffset();
int mod = (offset % POIFSConstants.BIG_BLOCK_SIZE);
int mod = (offset % POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
if (mod != 0) {
mod = POIFSConstants.BIG_BLOCK_SIZE - mod;
mod = POIFSConstants.SMALLER_BIG_BLOCK_SIZE - mod;
byte[] buf = new byte[mod];
docStream.write(buf);
}

View File

@ -18,6 +18,8 @@
package org.apache.poi.poifs.filesystem;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@ -25,6 +27,9 @@ import junit.framework.TestCase;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.storage.HeaderBlockReader;
import org.apache.poi.poifs.storage.RawDataBlockList;
/**
* Tests for POIFSFileSystem
@ -168,6 +173,34 @@ public final class TestPOIFSFileSystem extends TestCase {
assertTrue(msg.startsWith("Your file contains 695 sectors"));
}
}
/**
* Most OLE2 files use 512byte blocks. However, a small number
* use 4k blocks. Check that we can open these.
* DISABLED until we get a sample 4k block file that's under 22mb...
*/
public void DISABLEDtest4KBlocks() throws Exception {
InputStream inp = new FileInputStream(new File("/home/nick/Downloads/IP-ConvertImage-01.zvi"));
// First up, check that we can process the header properly
HeaderBlockReader header_block_reader = new HeaderBlockReader(inp);
POIFSBigBlockSize bigBlockSize = header_block_reader.getBigBlockSize();
assertEquals(4096, bigBlockSize.getBigBlockSize());
// Check the fat info looks sane
assertEquals(109, header_block_reader.getBATArray().length);
assertTrue(header_block_reader.getBATCount() > 5);
assertEquals(0, header_block_reader.getXBATCount());
// Now check we can get the basic fat
RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
// Now try and open properly
POIFSFileSystem fs = new POIFSFileSystem(
new FileInputStream(new File("/home/nick/Downloads/IP-ConvertImage-01.zvi"))
);
}
private static InputStream openSampleStream(String sampleFileName) {
return HSSFTestDataSamples.openSampleFileStream(sampleFileName);

View File

@ -70,7 +70,7 @@ public final class TestPropertyTable extends TestCase {
public void testWriterPropertyTable() throws IOException {
// create the PropertyTable
PropertyTable table = new PropertyTable();
PropertyTable table = new PropertyTable(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
// create three DocumentProperty instances and add them to the
// PropertyTable
@ -430,15 +430,17 @@ public final class TestPropertyTable extends TestCase {
};
RawDataBlockList data_blocks = new RawDataBlockList(new ByteArrayInputStream(RawDataUtil
.decode(raw_data_array)), POIFSConstants.BIG_BLOCK_SIZE);
.decode(raw_data_array)), POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
int[] bat_array = { 15 };
// need to initialize the block list with a block allocation
// table
new BlockAllocationTableReader(1, bat_array, 0, -2, data_blocks);
new BlockAllocationTableReader(
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 1, bat_array, 0, -2, data_blocks);
// get property table from the document
PropertyTable table = new PropertyTable(0, data_blocks);
PropertyTable table = new PropertyTable(
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 0, data_blocks);
assertEquals(30 * 64, table.getRoot().getSize());
int count = 0;

View File

@ -38,7 +38,7 @@ public final class LocalRawDataBlockList extends RawDataBlockList {
public LocalRawDataBlockList()
throws IOException
{
super(new ByteArrayInputStream(new byte[ 0 ]), POIFSConstants.BIG_BLOCK_SIZE);
super(new ByteArrayInputStream(new byte[ 0 ]), POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
_list = new ArrayList<RawDataBlock>();
_array = null;
}

View File

@ -21,6 +21,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import org.apache.poi.poifs.common.POIFSConstants;
import junit.framework.TestCase;
/**
@ -39,27 +41,27 @@ public final class TestBATBlock extends TestCase {
public void testCreateBATBlocks() throws IOException {
// test 0 length array (basic sanity)
BATBlock[] rvalue = BATBlock.createBATBlocks(createTestArray(0));
BATBlock[] rvalue = BATBlock.createBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(0));
assertEquals(0, rvalue.length);
// test array of length 1
rvalue = BATBlock.createBATBlocks(createTestArray(1));
rvalue = BATBlock.createBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(1));
assertEquals(1, rvalue.length);
verifyContents(rvalue, 1);
// test array of length 127
rvalue = BATBlock.createBATBlocks(createTestArray(127));
rvalue = BATBlock.createBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(127));
assertEquals(1, rvalue.length);
verifyContents(rvalue, 127);
// test array of length 128
rvalue = BATBlock.createBATBlocks(createTestArray(128));
rvalue = BATBlock.createBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(128));
assertEquals(1, rvalue.length);
verifyContents(rvalue, 128);
// test array of length 129
rvalue = BATBlock.createBATBlocks(createTestArray(129));
rvalue = BATBlock.createBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(129));
assertEquals(2, rvalue.length);
verifyContents(rvalue, 129);
}
@ -105,32 +107,32 @@ public final class TestBATBlock extends TestCase {
public void testCreateXBATBlocks() throws IOException {
// test 0 length array (basic sanity)
BATBlock[] rvalue = BATBlock.createXBATBlocks(createTestArray(0), 1);
BATBlock[] rvalue = BATBlock.createXBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(0), 1);
assertEquals(0, rvalue.length);
// test array of length 1
rvalue = BATBlock.createXBATBlocks(createTestArray(1), 1);
rvalue = BATBlock.createXBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(1), 1);
assertEquals(1, rvalue.length);
verifyXBATContents(rvalue, 1, 1);
// test array of length 127
rvalue = BATBlock.createXBATBlocks(createTestArray(127), 1);
rvalue = BATBlock.createXBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(127), 1);
assertEquals(1, rvalue.length);
verifyXBATContents(rvalue, 127, 1);
// test array of length 128
rvalue = BATBlock.createXBATBlocks(createTestArray(128), 1);
rvalue = BATBlock.createXBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(128), 1);
assertEquals(2, rvalue.length);
verifyXBATContents(rvalue, 128, 1);
// test array of length 254
rvalue = BATBlock.createXBATBlocks(createTestArray(254), 1);
rvalue = BATBlock.createXBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(254), 1);
assertEquals(2, rvalue.length);
verifyXBATContents(rvalue, 254, 1);
// test array of length 255
rvalue = BATBlock.createXBATBlocks(createTestArray(255), 1);
rvalue = BATBlock.createXBATBlocks(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, createTestArray(255), 1);
assertEquals(3, rvalue.length);
verifyXBATContents(rvalue, 255, 1);
}
@ -193,17 +195,17 @@ public final class TestBATBlock extends TestCase {
{
assertEquals(
"requirement for " + blockCounts[ j ], requirements[ j ],
BATBlock.calculateXBATStorageRequirements(blockCounts[ j ]));
BATBlock.calculateXBATStorageRequirements(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, blockCounts[ j ]));
}
}
public void testEntriesPerBlock() {
assertEquals(128, BATBlock.entriesPerBlock());
assertEquals(128, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS.getBATEntriesPerBlock());
}
public void testEntriesPerXBATBlock() {
assertEquals(127, BATBlock.entriesPerXBATBlock());
assertEquals(127, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS.getXBATEntriesPerBlock());
}
public void testGetXBATChainOffset() {
assertEquals(508, BATBlock.getXBATChainOffset());
assertEquals(508, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS.getNextXBATChainOffset());
}
}

View File

@ -25,6 +25,7 @@ import java.util.Arrays;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.HexRead;
import org.apache.poi.util.LittleEndian;
@ -187,8 +188,9 @@ public final class TestBlockAllocationTableReader extends TestCase {
sbts[j] = new RawDataBlock(sbt_input);
}
SmallDocumentBlockList small_blocks = new SmallDocumentBlockList(SmallDocumentBlock
.extract(sbts));
BlockAllocationTableReader sbat = new BlockAllocationTableReader(sbats, small_blocks);
.extract(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, sbts));
BlockAllocationTableReader sbat = new BlockAllocationTableReader(
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, sbats, small_blocks);
boolean[] isUsed = {
false, false, false, false, false, false, false, false, false,
false, true, true, true, true, true, true, true, true, true, true,
@ -271,7 +273,8 @@ public final class TestBlockAllocationTableReader extends TestCase {
}
list.fill(132);
int[] blocks = { 2, 3 };
BlockAllocationTableReader table = new BlockAllocationTableReader(130, blocks, 2, 0, list);
BlockAllocationTableReader table = new BlockAllocationTableReader(
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 130, blocks, 2, 0, list);
for (int i = 0; i < (130 * 128); i++) {
if (i % 256 == 0) {
@ -353,7 +356,8 @@ public final class TestBlockAllocationTableReader extends TestCase {
list.add(new RawDataBlock(new ByteArrayInputStream(data)));
list.fill(1);
int[] blocks = { 0 };
BlockAllocationTableReader table = new BlockAllocationTableReader(1, blocks, 0, -2, list);
BlockAllocationTableReader table = new BlockAllocationTableReader(
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 1, blocks, 0, -2, list);
int[] start_blocks = { -2, 1, 2, 3, 5, 7, 9, 11, 12 };
int[] expected_length = { 0, 1, -1, -1, -1, -1, -1, -1, 116 };
@ -384,6 +388,9 @@ public final class TestBlockAllocationTableReader extends TestCase {
*/
public void testBadSectorAllocationTableSize_bug48085() {
int BLOCK_SIZE = 512;
POIFSBigBlockSize bigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
assertEquals(BLOCK_SIZE, bigBlockSize.getBigBlockSize());
// 512 bytes take from the start of bugzilla attachment 24444
byte[] initData = HexRead.readFromString(
@ -402,12 +409,13 @@ public final class TestBlockAllocationTableReader extends TestCase {
RawDataBlockList dataBlocks;
try {
hb = new HeaderBlockReader(stream);
dataBlocks = new RawDataBlockList(stream, BLOCK_SIZE);
dataBlocks = new RawDataBlockList(stream, bigBlockSize);
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
new BlockAllocationTableReader(hb.getBATCount(), hb.getBATArray(), hb.getXBATCount(),
new BlockAllocationTableReader(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,
hb.getBATCount(), hb.getBATArray(), hb.getXBATCount(),
hb.getXBATIndex(), dataBlocks);
} catch (IOException e) {
// expected during successful test

View File

@ -36,7 +36,7 @@ public final class TestBlockAllocationTableWriter extends TestCase {
public void testAllocateSpace() {
BlockAllocationTableWriter table =
new BlockAllocationTableWriter();
new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
int[] blockSizes =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
@ -51,36 +51,36 @@ public final class TestBlockAllocationTableWriter extends TestCase {
}
public void testCreateBlocks() {
BlockAllocationTableWriter table = new BlockAllocationTableWriter();
BlockAllocationTableWriter table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
table.allocateSpace(127);
table.createBlocks();
verifyBlocksCreated(table, 1);
table = new BlockAllocationTableWriter();
table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
table.allocateSpace(128);
table.createBlocks();
verifyBlocksCreated(table, 2);
table = new BlockAllocationTableWriter();
table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
table.allocateSpace(254);
table.createBlocks();
verifyBlocksCreated(table, 2);
table = new BlockAllocationTableWriter();
table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
table.allocateSpace(255);
table.createBlocks();
verifyBlocksCreated(table, 3);
table = new BlockAllocationTableWriter();
table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
table.allocateSpace(13843);
table.createBlocks();
verifyBlocksCreated(table, 109);
table = new BlockAllocationTableWriter();
table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
table.allocateSpace(13844);
table.createBlocks();
verifyBlocksCreated(table, 110);
table = new BlockAllocationTableWriter();
table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
table.allocateSpace(13969);
table.createBlocks();
verifyBlocksCreated(table, 110);
table = new BlockAllocationTableWriter();
table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
table.allocateSpace(13970);
table.createBlocks();
verifyBlocksCreated(table, 111);
@ -90,7 +90,7 @@ public final class TestBlockAllocationTableWriter extends TestCase {
* Test content produced by BlockAllocationTableWriter
*/
public void testProduct() throws IOException {
BlockAllocationTableWriter table = new BlockAllocationTableWriter();
BlockAllocationTableWriter table = new BlockAllocationTableWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
for (int k = 1; k <= 22; k++)
{

View File

@ -25,6 +25,7 @@ import java.util.List;
import junit.framework.TestCase;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
@ -142,10 +143,10 @@ public final class TestBlockListImpl extends TestCase {
BlockListImpl list = create();
list.setBAT(null);
list.setBAT(new BlockAllocationTableReader());
list.setBAT(new BlockAllocationTableReader(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS));
try
{
list.setBAT(new BlockAllocationTableReader());
list.setBAT(new BlockAllocationTableReader(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS));
fail("second attempt should have failed");
}
catch (IOException ignored)
@ -233,7 +234,7 @@ public final class TestBlockListImpl extends TestCase {
0
};
BlockAllocationTableReader table =
new BlockAllocationTableReader(1, blocks, 0, -2, list);
new BlockAllocationTableReader(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 1, blocks, 0, -2, list);
int[] start_blocks =
{
-2, 1, 2, 3, 5, 7, 9, 11, 12

View File

@ -21,6 +21,8 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.poi.poifs.common.POIFSConstants;
import junit.framework.TestCase;
/**
@ -55,7 +57,7 @@ public final class TestDocumentBlock extends TestCase {
byte[] data = new byte[ Math.min(_testdata.length - index, 512) ];
System.arraycopy(_testdata, index, data, 0, data.length);
DocumentBlock block = new DocumentBlock(input);
DocumentBlock block = new DocumentBlock(input, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
verifyOutput(block, data);
size += block.size();

View File

@ -23,6 +23,7 @@ import java.io.IOException;
import junit.framework.TestCase;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
@ -46,7 +47,7 @@ public final class TestHeaderBlockWriter extends TestCase {
* Test creating a HeaderBlockWriter
*/
public void testConstructors() throws IOException {
HeaderBlockWriter block = new HeaderBlockWriter();
HeaderBlockWriter block = new HeaderBlockWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
ByteArrayOutputStream output = new ByteArrayOutputStream(512);
block.writeBlocks(output);
@ -85,7 +86,7 @@ public final class TestHeaderBlockWriter extends TestCase {
* Test setting the SBAT start block
*/
public void testSetSBATStart() throws IOException {
HeaderBlockWriter block = new HeaderBlockWriter();
HeaderBlockWriter block = new HeaderBlockWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
block.setSBATStart(0x01234567);
ByteArrayOutputStream output = new ByteArrayOutputStream(512);
@ -117,7 +118,7 @@ public final class TestHeaderBlockWriter extends TestCase {
* test setPropertyStart and getPropertyStart
*/
public void testSetPropertyStart() throws IOException {
HeaderBlockWriter block = new HeaderBlockWriter();
HeaderBlockWriter block = new HeaderBlockWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
block.setPropertyStart(0x01234567);
ByteArrayOutputStream output = new ByteArrayOutputStream(512);
@ -152,11 +153,11 @@ public final class TestHeaderBlockWriter extends TestCase {
public void testSetBATBlocks() throws IOException {
// first, a small set of blocks
HeaderBlockWriter block = new HeaderBlockWriter();
HeaderBlockWriter block = new HeaderBlockWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
BATBlock[] xbats = block.setBATBlocks(5, 0x01234567);
assertEquals(0, xbats.length);
assertEquals(0, HeaderBlockWriter.calculateXBATStorageRequirements(5));
assertEquals(0, HeaderBlockWriter.calculateXBATStorageRequirements(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,5));
ByteArrayOutputStream output = new ByteArrayOutputStream(512);
block.writeBlocks(output);
@ -183,10 +184,10 @@ public final class TestHeaderBlockWriter extends TestCase {
confirmEqual(expected, copy);
// second, a full set of blocks (109 blocks)
block = new HeaderBlockWriter();
block = new HeaderBlockWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
xbats = block.setBATBlocks(109, 0x01234567);
assertEquals(0, xbats.length);
assertEquals(0, HeaderBlockWriter.calculateXBATStorageRequirements(109));
assertEquals(0, HeaderBlockWriter.calculateXBATStorageRequirements(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,109));
output = new ByteArrayOutputStream(512);
block.writeBlocks(output);
copy = output.toByteArray();
@ -211,10 +212,10 @@ public final class TestHeaderBlockWriter extends TestCase {
confirmEqual(expected2, copy);
// finally, a really large set of blocks (256 blocks)
block = new HeaderBlockWriter();
block = new HeaderBlockWriter(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
xbats = block.setBATBlocks(256, 0x01234567);
assertEquals(2, xbats.length);
assertEquals(2, HeaderBlockWriter.calculateXBATStorageRequirements(256));
assertEquals(2, HeaderBlockWriter.calculateXBATStorageRequirements(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,256));
output = new ByteArrayOutputStream(512);
block.writeBlocks(output);
copy = output.toByteArray();

View File

@ -22,6 +22,8 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.poifs.common.POIFSConstants;
import junit.framework.TestCase;
/**
@ -36,13 +38,13 @@ public final class TestPropertyBlock extends TestCase {
// test with 0 properties
List properties = new ArrayList();
BlockWritable[] blocks =
PropertyBlock.createPropertyBlockArray(properties);
PropertyBlock.createPropertyBlockArray(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,properties);
assertEquals(0, blocks.length);
// test with 1 property
properties.add(new LocalProperty("Root Entry"));
blocks = PropertyBlock.createPropertyBlockArray(properties);
blocks = PropertyBlock.createPropertyBlockArray(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,properties);
assertEquals(1, blocks.length);
byte[] testblock = new byte[ 512 ];
@ -66,7 +68,7 @@ public final class TestPropertyBlock extends TestCase {
// test with 3 properties
properties.add(new LocalProperty("workbook"));
properties.add(new LocalProperty("summary"));
blocks = PropertyBlock.createPropertyBlockArray(properties);
blocks = PropertyBlock.createPropertyBlockArray(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,properties);
assertEquals(1, blocks.length);
testblock[ 0x0080 ] = ( byte ) 'w';
testblock[ 0x0082 ] = ( byte ) 'o';
@ -89,7 +91,7 @@ public final class TestPropertyBlock extends TestCase {
// test with 4 properties
properties.add(new LocalProperty("wintery"));
blocks = PropertyBlock.createPropertyBlockArray(properties);
blocks = PropertyBlock.createPropertyBlockArray(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,properties);
assertEquals(1, blocks.length);
testblock[ 0x0180 ] = ( byte ) 'w';
testblock[ 0x0182 ] = ( byte ) 'i';
@ -103,7 +105,7 @@ public final class TestPropertyBlock extends TestCase {
// test with 5 properties
properties.add(new LocalProperty("foo"));
blocks = PropertyBlock.createPropertyBlockArray(properties);
blocks = PropertyBlock.createPropertyBlockArray(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,properties);
assertEquals(2, blocks.length);
testblock = new byte[ 1024 ];
for (int j = 0; j < 8; j++)

View File

@ -51,14 +51,14 @@ public final class TestRawDataBlockList extends TestCase {
{
data[ j ] = ( byte ) j;
}
new RawDataBlockList(new ByteArrayInputStream(data), POIFSConstants.BIG_BLOCK_SIZE);
new RawDataBlockList(new ByteArrayInputStream(data), POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
}
/**
* Test creating an empty RawDataBlockList
*/
public void testEmptyConstructor() throws IOException {
new RawDataBlockList(new ByteArrayInputStream(new byte[ 0 ]), POIFSConstants.BIG_BLOCK_SIZE);
new RawDataBlockList(new ByteArrayInputStream(new byte[ 0 ]), POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
}
/**
@ -84,7 +84,7 @@ public final class TestRawDataBlockList extends TestCase {
// Check we logged the error
logger.reset();
new RawDataBlockList(new ByteArrayInputStream(data), POIFSConstants.BIG_BLOCK_SIZE);
new RawDataBlockList(new ByteArrayInputStream(data), POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
assertEquals(1, logger.logged.size());
}
}

View File

@ -296,17 +296,18 @@ public final class TestSmallBlockTableReader extends TestCase {
};
RawDataBlockList data_blocks = new RawDataBlockList(new ByteArrayInputStream(RawDataUtil
.decode(raw_data_array)), POIFSConstants.BIG_BLOCK_SIZE);
.decode(raw_data_array)), POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
int[] bat_array = { 15 };
// need to initialize the block list with a block allocation
// table
new BlockAllocationTableReader(1, bat_array, 0, -2, data_blocks);
new BlockAllocationTableReader(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 1, bat_array, 0, -2, data_blocks);
// get property table from the document
PropertyTable properties = new PropertyTable(0, data_blocks);
PropertyTable properties = new PropertyTable(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 0, data_blocks);
RootProperty root = properties.getRoot();
BlockList bl = SmallBlockTableReader.getSmallDocumentBlocks(data_blocks, root, 14);
BlockList bl = SmallBlockTableReader.getSmallDocumentBlocks(
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, data_blocks, root, 14);
assertNotNull(bl);
}
}

View File

@ -24,6 +24,7 @@ import java.util.List;
import junit.framework.TestCase;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.POIFSDocument;
import org.apache.poi.poifs.property.PropertyTable;
import org.apache.poi.poifs.property.RootProperty;
@ -74,9 +75,9 @@ public final class TestSmallBlockTableWriter extends TestCase {
documents
.add(new POIFSDocument("doc9",
new ByteArrayInputStream(new byte[ 9 ])));
RootProperty root = new PropertyTable().getRoot();
SmallBlockTableWriter sbtw = new SmallBlockTableWriter(documents,
root);
RootProperty root = new PropertyTable(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS).getRoot();
SmallBlockTableWriter sbtw = new SmallBlockTableWriter(
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, documents,root);
BlockAllocationTableWriter bat = sbtw.getSBAT();
// 15 small blocks: 6 for doc340, 0 for doc5000 (too big), 0

View File

@ -24,6 +24,8 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.poifs.common.POIFSConstants;
import junit.framework.TestCase;
/**
@ -55,7 +57,7 @@ public final class TestSmallDocumentBlock extends TestCase {
while (true)
{
DocumentBlock block = new DocumentBlock(stream);
DocumentBlock block = new DocumentBlock(stream,POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
documents.add(block);
if (block.partiallyRead())
@ -65,7 +67,7 @@ public final class TestSmallDocumentBlock extends TestCase {
}
SmallDocumentBlock[] results =
SmallDocumentBlock
.convert(( BlockWritable [] ) documents
.convert(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,( BlockWritable [] ) documents
.toArray(new DocumentBlock[ 0 ]), _testdata_size);
assertEquals("checking correct result size: ",
@ -108,8 +110,8 @@ public final class TestSmallDocumentBlock extends TestCase {
{
array[ k ] = ( byte ) k;
}
SmallDocumentBlock[] blocks = SmallDocumentBlock.convert(array,
319);
SmallDocumentBlock[] blocks = SmallDocumentBlock.convert(
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, array, 319);
assertEquals(5, blocks.length);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
@ -146,7 +148,7 @@ public final class TestSmallDocumentBlock extends TestCase {
{
foo.add(new Object());
}
int result = SmallDocumentBlock.fill(foo);
int result = SmallDocumentBlock.fill(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,foo);
assertEquals("correct big block count: ", (j + 7) / 8, result);
assertEquals("correct small block count: ", 8 * result,
@ -206,7 +208,7 @@ public final class TestSmallDocumentBlock extends TestCase {
{
new RawDataBlock(new ByteArrayInputStream(data))
};
List output = SmallDocumentBlock.extract(blocks);
List output = SmallDocumentBlock.extract(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,blocks);
Iterator iter = output.iterator();
offset = 0;

View File

@ -20,6 +20,8 @@ package org.apache.poi.poifs.storage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.apache.poi.poifs.common.POIFSConstants;
import junit.framework.TestCase;
/**
@ -44,7 +46,7 @@ public final class TestSmallDocumentBlockList extends TestCase {
blocks[ j ] = new RawDataBlock(stream);
}
SmallDocumentBlockList sdbl =
new SmallDocumentBlockList(SmallDocumentBlock.extract(blocks));
new SmallDocumentBlockList(SmallDocumentBlock.extract(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,blocks));
// proof we added the blocks
for (int j = 0; j < 40; j++)