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> * <p>A repository for constants shared by POI classes.</p>
*
* @author Marc Johnson (mjohnson at apache dot org)
*/ */
public interface POIFSConstants public interface POIFSConstants
{ {
/** Most files use 512 bytes as their big block size */ /** 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 */ /** Some use 4096 bytes */
public static final int LARGER_BIG_BLOCK_SIZE = 0x1000; 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; 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 // set up the block allocation table (necessary for the
// data_blocks to be manageable // 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.getBATArray(),
header_block_reader.getXBATCount(), header_block_reader.getXBATCount(),
header_block_reader.getXBATIndex(), header_block_reader.getXBATIndex(),
@ -90,14 +91,17 @@ public class POIFSReader
// get property table from the document // get property table from the document
PropertyTable properties = PropertyTable properties =
new PropertyTable(header_block_reader.getPropertyStart(), new PropertyTable(header_block_reader.getBigBlockSize(),
header_block_reader.getPropertyStart(),
data_blocks); data_blocks);
// process documents // process documents
processProperties(SmallBlockTableReader processProperties(SmallBlockTableReader
.getSmallDocumentBlocks(data_blocks, properties .getSmallDocumentBlocks(
.getRoot(), header_block_reader header_block_reader.getBigBlockSize(),
.getSBATStart()), data_blocks, properties.getRoot() data_blocks, properties.getRoot(),
header_block_reader.getSBATStart()),
data_blocks, properties.getRoot()
.getChildren(), new POIFSDocumentPath()); .getChildren(), new POIFSDocumentPath());
} }

View File

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

View File

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

View File

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

View File

@ -22,6 +22,7 @@ import java.io.OutputStream;
import java.util.Arrays; import java.util.Arrays;
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.util.IntegerField; import org.apache.poi.util.IntegerField;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
@ -33,12 +34,6 @@ import org.apache.poi.util.LittleEndianConsts;
* @author Marc Johnson (mjohnson at apache dot org) * @author Marc Johnson (mjohnson at apache dot org)
*/ */
public final class BATBlock extends BigBlock { 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 static final byte _default_value = ( byte ) 0xFF;
private IntegerField[] _fields; private IntegerField[] _fields;
private byte[] _data; private byte[] _data;
@ -47,9 +42,13 @@ public final class BATBlock extends BigBlock {
* Create a single instance initialized with default values * 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); Arrays.fill(_data, _default_value);
_fields = new IntegerField[ _entries_per_block ]; _fields = new IntegerField[ _entries_per_block ];
int offset = 0; int offset = 0;
@ -70,16 +69,17 @@ public final class BATBlock extends BigBlock {
* @return the newly created array of BATBlocks * @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 ]; BATBlock[] blocks = new BATBlock[ block_count ];
int index = 0; int index = 0;
int remaining = entries.length; int remaining = entries.length;
int _entries_per_block = bigBlockSize.getBATEntriesPerBlock();
for (int j = 0; j < entries.length; j += _entries_per_block) 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) (remaining > _entries_per_block)
? j + _entries_per_block ? j + _entries_per_block
: entries.length); : entries.length);
@ -98,21 +98,23 @@ public final class BATBlock extends BigBlock {
* @return the newly created array of BATBlocks * @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) final int startBlock)
{ {
int block_count = int block_count =
calculateXBATStorageRequirements(entries.length); calculateXBATStorageRequirements(bigBlockSize, entries.length);
BATBlock[] blocks = new BATBlock[ block_count ]; BATBlock[] blocks = new BATBlock[ block_count ];
int index = 0; int index = 0;
int remaining = entries.length; int remaining = entries.length;
int _entries_per_xbat_block = bigBlockSize.getXBATEntriesPerBlock();
if (block_count != 0) if (block_count != 0)
{ {
for (int j = 0; j < entries.length; j += _entries_per_xbat_block) for (int j = 0; j < entries.length; j += _entries_per_xbat_block)
{ {
blocks[ index++ ] = blocks[ index++ ] =
new BATBlock(entries, j, new BATBlock(bigBlockSize, entries, j,
(remaining > _entries_per_xbat_block) (remaining > _entries_per_xbat_block)
? j + _entries_per_xbat_block ? j + _entries_per_xbat_block
: entries.length); : entries.length);
@ -120,9 +122,9 @@ public final class BATBlock extends BigBlock {
} }
for (index = 0; index < blocks.length - 1; index++) 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; return blocks;
} }
@ -136,8 +138,9 @@ public final class BATBlock extends BigBlock {
* @return the number of BATBlocks needed * @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; 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 * @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) return (entryCount + _entries_per_xbat_block - 1)
/ _entries_per_xbat_block; / _entries_per_xbat_block;
} }
/** private void setXBATChain(final POIFSBigBlockSize bigBlockSize, int chainIndex)
* @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)
{ {
int _entries_per_xbat_block = bigBlockSize.getXBATEntriesPerBlock();
_fields[ _entries_per_xbat_block ].set(chainIndex, _data); _fields[ _entries_per_xbat_block ].set(chainIndex, _data);
} }
@ -199,10 +177,10 @@ public final class BATBlock extends BigBlock {
* k, start_index <= k < end_index) * k, start_index <= k < end_index)
*/ */
private BATBlock(final int [] entries, final int start_index, private BATBlock(POIFSBigBlockSize bigBlockSize, final int [] entries,
final int end_index) final int start_index, final int end_index)
{ {
this(); this(bigBlockSize);
for (int k = start_index; k < end_index; k++) for (int k = start_index; k < end_index; k++)
{ {
_fields[ k - start_index ].set(entries[ k ], _data); _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.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
abstract class BigBlock abstract class BigBlock
implements BlockWritable 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 * Default implementation of write for extending classes that

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import java.util.*; import java.util.*;
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.util.IntList; import org.apache.poi.util.IntList;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
@ -56,6 +57,7 @@ public final class BlockAllocationTableReader {
*/ */
private static final int MAX_BLOCK_COUNT = 65535; private static final int MAX_BLOCK_COUNT = 65535;
private final IntList _entries; private final IntList _entries;
private POIFSBigBlockSize bigBlockSize;
/** /**
* create a BlockAllocationTableReader for an existing filesystem. Side * 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 * @exception IOException if, in trying to create the table, we
* encounter logic errors * 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 { int xbat_count, int xbat_index, BlockList raw_block_list) throws IOException {
this(); this(bigBlockSize);
if (block_count <= 0) { if (block_count <= 0) {
throw new IOException( throw new IOException(
"Illegal block count; minimum count is 1, got " + block_count "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"); "BAT count exceeds limit, yet XBAT index indicates no valid entries");
} }
int chain_index = xbat_index; int chain_index = xbat_index;
int max_entries_per_block = BATBlock.entriesPerXBATBlock(); int max_entries_per_block = bigBlockSize.getXBATEntriesPerBlock();
int chain_index_offset = BATBlock.getXBATChainOffset(); int chain_index_offset = bigBlockSize.getNextXBATChainOffset();
// Each XBAT block contains either: // Each XBAT block contains either:
// (maximum number of sector indexes) + index of next XBAT // (maximum number of sector indexes) + index of next XBAT
@ -173,13 +176,14 @@ public final class BlockAllocationTableReader {
* *
* @exception IOException * @exception IOException
*/ */
BlockAllocationTableReader(ListManagedBlock[] blocks, BlockList raw_block_list) BlockAllocationTableReader(POIFSBigBlockSize bigBlockSize, ListManagedBlock[] blocks, BlockList raw_block_list)
throws IOException { throws IOException {
this(); this(bigBlockSize);
setEntries(blocks, raw_block_list); setEntries(blocks, raw_block_list);
} }
BlockAllocationTableReader() { BlockAllocationTableReader(POIFSBigBlockSize bigBlockSize) {
this.bigBlockSize = bigBlockSize;
_entries = new IntList(); _entries = new IntList();
} }
@ -279,7 +283,7 @@ public final class BlockAllocationTableReader {
* blocks will be eliminated from the list * blocks will be eliminated from the list
*/ */
private void setEntries(ListManagedBlock[] blocks, BlockList raw_blocks) throws IOException { 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++) 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.IOException;
import java.io.OutputStream; import java.io.OutputStream;
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.BATManaged; import org.apache.poi.poifs.filesystem.BATManaged;
import org.apache.poi.util.IntList; import org.apache.poi.util.IntList;
@ -43,15 +44,17 @@ public final class BlockAllocationTableWriter implements BlockWritable, BATManag
private IntList _entries; private IntList _entries;
private BATBlock[] _blocks; private BATBlock[] _blocks;
private int _start_block; private int _start_block;
private POIFSBigBlockSize _bigBlockSize;
/** /**
* create a BlockAllocationTableWriter * create a BlockAllocationTableWriter
*/ */
public BlockAllocationTableWriter() public BlockAllocationTableWriter(POIFSBigBlockSize bigBlockSize)
{ {
_start_block = POIFSConstants.END_OF_CHAIN; _bigBlockSize = bigBlockSize;
_entries = new IntList(); _start_block = POIFSConstants.END_OF_CHAIN;
_blocks = new BATBlock[ 0 ]; _entries = new IntList();
_blocks = new BATBlock[ 0 ];
} }
/** /**
@ -67,12 +70,13 @@ public final class BlockAllocationTableWriter implements BlockWritable, BATManag
while (true) while (true)
{ {
int calculated_bat_blocks = int calculated_bat_blocks =
BATBlock.calculateStorageRequirements(bat_blocks BATBlock.calculateStorageRequirements(_bigBlockSize,
bat_blocks
+ xbat_blocks + xbat_blocks
+ _entries.size()); + _entries.size());
int calculated_xbat_blocks = int calculated_xbat_blocks =
HeaderBlockWriter HeaderBlockWriter.calculateXBATStorageRequirements(
.calculateXBATStorageRequirements(calculated_bat_blocks); _bigBlockSize, calculated_bat_blocks);
if ((bat_blocks == calculated_bat_blocks) if ((bat_blocks == calculated_bat_blocks)
&& (xbat_blocks == calculated_xbat_blocks)) && (xbat_blocks == calculated_xbat_blocks))
@ -131,7 +135,7 @@ public final class BlockAllocationTableWriter implements BlockWritable, BATManag
*/ */
void simpleCreateBlocks() 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.io.OutputStream;
import java.util.Arrays; import java.util.Arrays;
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.util.IOUtils; import org.apache.poi.util.IOUtils;
@ -50,6 +51,11 @@ public final class DocumentBlock extends BigBlock {
public DocumentBlock(final RawDataBlock block) public DocumentBlock(final RawDataBlock block)
throws IOException 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(); _data = block.getData();
_bytes_read = _data.length; _bytes_read = _data.length;
} }
@ -62,10 +68,10 @@ public final class DocumentBlock extends BigBlock {
* @exception IOException * @exception IOException
*/ */
public DocumentBlock(final InputStream stream) public DocumentBlock(final InputStream stream, POIFSBigBlockSize bigBlockSize)
throws IOException throws IOException
{ {
this(); this(bigBlockSize);
int count = IOUtils.readFully(stream, _data); int count = IOUtils.readFully(stream, _data);
_bytes_read = (count == -1) ? 0 _bytes_read = (count == -1) ? 0
@ -76,9 +82,10 @@ public final class DocumentBlock extends BigBlock {
* Create a single instance initialized with default values * 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); Arrays.fill(_data, _default_value);
} }
@ -101,7 +108,7 @@ public final class DocumentBlock extends BigBlock {
public boolean partiallyRead() 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 * input array
*/ */
public static DocumentBlock [] convert(final byte [] array, public static DocumentBlock [] convert(final POIFSBigBlockSize bigBlockSize,
final byte [] array,
final int size) final int size)
{ {
DocumentBlock[] rval = 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; int offset = 0;
for (int k = 0; k < rval.length; k++) for (int k = 0; k < rval.length; k++)
{ {
rval[ k ] = new DocumentBlock(); rval[ k ] = new DocumentBlock(bigBlockSize);
if (offset < array.length) if (offset < array.length)
{ {
int length = Math.min(POIFSConstants.BIG_BLOCK_SIZE, int length = Math.min(bigBlockSize.getBigBlockSize(),
array.length - offset); array.length - offset);
System.arraycopy(array, offset, rval[ k ]._data, 0, length); 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, Arrays.fill(rval[ k ]._data, length,
POIFSConstants.BIG_BLOCK_SIZE, bigBlockSize.getBigBlockSize(),
_default_value); _default_value);
} }
} }
@ -151,7 +159,7 @@ public final class DocumentBlock extends BigBlock {
{ {
Arrays.fill(rval[ k ]._data, _default_value); Arrays.fill(rval[ k ]._data, _default_value);
} }
offset += POIFSConstants.BIG_BLOCK_SIZE; offset += bigBlockSize.getBigBlockSize();
} }
return rval; return rval;
} }

View File

@ -30,8 +30,8 @@ public interface HeaderBlockConstants
public static final long _signature = 0xE11AB1A1E011CFD0L; public static final long _signature = 0xE11AB1A1E011CFD0L;
public static final int _bat_array_offset = 0x4c; public static final int _bat_array_offset = 0x4c;
public static final int _max_bats_in_header = public static final int _max_bats_in_header =
(POIFSConstants.BIG_BLOCK_SIZE - _bat_array_offset) (POIFSConstants.SMALLER_BIG_BLOCK_SIZE - _bat_array_offset)
/ LittleEndianConsts.INT_SIZE; / LittleEndianConsts.INT_SIZE; // If 4k blocks, rest is blank
// Note - in Microsoft terms: // Note - in Microsoft terms:
// BAT ~= FAT // 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.IOException;
import java.io.InputStream; import java.io.InputStream;
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.util.HexDump; import org.apache.poi.util.HexDump;
@ -48,7 +49,7 @@ public final class HeaderBlockReader {
* 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
*/ */
private final int bigBlockSize; private final POIFSBigBlockSize bigBlockSize;
/** /**
* number of big block allocation table blocks (int). * number of big block allocation table blocks (int).
@ -130,20 +131,20 @@ public final class HeaderBlockReader {
// Figure out our block size // Figure out our block size
switch (blockStart[30]) { switch (blockStart[30]) {
case 12: case 12:
bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE; break; bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS; break;
case 9: case 9:
bigBlockSize = POIFSConstants.BIG_BLOCK_SIZE; break; bigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS; break;
default: default:
throw new IOException("Unsupported blocksize (2^" throw new IOException("Unsupported blocksize (2^"
+ blockStart[30] + "). Expected 2^9 or 2^12."); + 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); System.arraycopy(blockStart, 0, _data, 0, blockStart.length);
// Now we can read the rest of our header // Now we can read the rest of our header
int byte_count = IOUtils.readFully(stream, _data, blockStart.length, _data.length - blockStart.length); int byte_count = IOUtils.readFully(stream, _data, blockStart.length, _data.length - blockStart.length);
if (byte_count+bsCount != bigBlockSize) { if (byte_count+bsCount != bigBlockSize.getBigBlockSize()) {
throw alertShortRead(byte_count, bigBlockSize); throw alertShortRead(byte_count, bigBlockSize.getBigBlockSize());
} }
_bat_count = getInt(_bat_count_offset, _data); _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 * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
*/ */
public int getBigBlockSize() { public POIFSBigBlockSize getBigBlockSize() {
return bigBlockSize; return bigBlockSize;
} }
} }

View File

@ -23,6 +23,7 @@ import java.io.*;
import java.util.*; import java.util.*;
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.util.IntegerField; import org.apache.poi.util.IntegerField;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
@ -64,9 +65,11 @@ public class HeaderBlockWriter
* Create a single instance initialized with default values * 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); Arrays.fill(_data, _default_value);
new LongField(_signature_offset, _signature, _data); new LongField(_signature_offset, _signature, _data);
new IntegerField(0x08, 0, _data); new IntegerField(0x08, 0, _data);
@ -76,7 +79,15 @@ public class HeaderBlockWriter
new ShortField(0x18, ( short ) 0x3b, _data); new ShortField(0x18, ( short ) 0x3b, _data);
new ShortField(0x1a, ( short ) 0x3, _data); new ShortField(0x1a, ( short ) 0x3, _data);
new ShortField(0x1c, ( short ) -2, _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(0x20, 0x6, _data);
new IntegerField(0x24, 0, _data); new IntegerField(0x24, 0, _data);
new IntegerField(0x28, 0, _data); new IntegerField(0x28, 0, _data);
@ -131,13 +142,13 @@ public class HeaderBlockWriter
excess_block_array[ j ] = startBlock + j excess_block_array[ j ] = startBlock + j
+ _max_bats_in_header; + _max_bats_in_header;
} }
rvalue = BATBlock.createXBATBlocks(excess_block_array, rvalue = BATBlock.createXBATBlocks(bigBlockSize, excess_block_array,
startBlock + blockCount); startBlock + blockCount);
_xbat_start.set(startBlock + blockCount, _data); _xbat_start.set(startBlock + blockCount, _data);
} }
else 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_start.set(POIFSConstants.END_OF_CHAIN, _data);
} }
_xbat_count.set(rvalue.length, _data); _xbat_count.set(rvalue.length, _data);
@ -188,11 +199,11 @@ public class HeaderBlockWriter
* @return number of XBAT blocks needed * @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) return (blockCount > _max_bats_in_header)
? BATBlock.calculateXBATStorageRequirements(blockCount ? BATBlock.calculateXBATStorageRequirements(
- _max_bats_in_header) bigBlockSize, blockCount - _max_bats_in_header)
: 0; : 0;
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -19,6 +19,7 @@
package org.apache.poi.poifs.storage; 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.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.BATManaged; import org.apache.poi.poifs.filesystem.BATManaged;
import org.apache.poi.poifs.filesystem.POIFSDocument; import org.apache.poi.poifs.filesystem.POIFSDocument;
@ -50,10 +51,11 @@ public class SmallBlockTableWriter
* @param root the Filesystem's root property * @param root the Filesystem's root property
*/ */
public SmallBlockTableWriter(final List documents, public SmallBlockTableWriter(final POIFSBigBlockSize bigBlockSize,
final List documents,
final RootProperty root) final RootProperty root)
{ {
_sbat = new BlockAllocationTableWriter(); _sbat = new BlockAllocationTableWriter(bigBlockSize);
_small_blocks = new ArrayList(); _small_blocks = new ArrayList();
_root = root; _root = root;
Iterator iter = documents.iterator(); Iterator iter = documents.iterator();
@ -76,7 +78,7 @@ public class SmallBlockTableWriter
} }
_sbat.simpleCreateBlocks(); _sbat.simpleCreateBlocks();
_root.setSize(_small_blocks.size()); _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.Arrays;
import java.util.List; import java.util.List;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants; 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_size = 1 << BLOCK_SHIFT;
private static final int BLOCK_MASK = _block_size-1; private static final int BLOCK_MASK = _block_size-1;
private static final int _blocks_per_big_block = private final int _blocks_per_big_block;
POIFSConstants.BIG_BLOCK_SIZE / _block_size; 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); 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 ]; _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 * 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 * @return an array of SmallDocumentBlock instances, filled from
* the array * the array
*/ */
public static SmallDocumentBlock [] convert(byte [] array, public static SmallDocumentBlock [] convert(POIFSBigBlockSize bigBlockSize,
byte [] array,
int size) int size)
{ {
SmallDocumentBlock[] rval = SmallDocumentBlock[] rval =
@ -73,7 +82,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
for (int k = 0; k < rval.length; k++) for (int k = 0; k < rval.length; k++)
{ {
rval[ k ] = new SmallDocumentBlock(); rval[ k ] = new SmallDocumentBlock(bigBlockSize);
if (offset < array.length) if (offset < array.length)
{ {
int length = Math.min(_block_size, array.length - offset); 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 * @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 count = blocks.size();
int big_block_count = (count + _blocks_per_big_block - 1) int big_block_count = (count + _blocks_per_big_block - 1)
/ _blocks_per_big_block; / _blocks_per_big_block;
@ -111,7 +122,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
for (; count < full_count; count++) for (; count < full_count; count++)
{ {
blocks.add(makeEmptySmallDocumentBlock()); blocks.add(makeEmptySmallDocumentBlock(bigBlockSize));
} }
return big_block_count; return big_block_count;
} }
@ -128,7 +139,8 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
* @exception ArrayIndexOutOfBoundsException if, somehow, the store * @exception ArrayIndexOutOfBoundsException if, somehow, the store
* contains less data than size indicates * contains less data than size indicates
*/ */
public static SmallDocumentBlock [] convert(BlockWritable [] store, public static SmallDocumentBlock [] convert(POIFSBigBlockSize bigBlockSize,
BlockWritable [] store,
int size) int size)
throws IOException, ArrayIndexOutOfBoundsException throws IOException, ArrayIndexOutOfBoundsException
{ {
@ -144,7 +156,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
for (int index = 0; index < rval.length; index++) for (int index = 0; index < rval.length; index++)
{ {
rval[ index ] = new SmallDocumentBlock(data, index); rval[ index ] = new SmallDocumentBlock(bigBlockSize, data, index);
} }
return rval; return rval;
} }
@ -157,9 +169,11 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
* *
* @return a List of SmallDocumentBlock's extracted from the input * @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 throws IOException
{ {
int _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize);
List sdbs = new ArrayList(); List sdbs = new ArrayList();
for (int j = 0; j < blocks.length; j++) 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++) 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; return sdbs;
@ -192,9 +206,9 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
return size * _block_size; 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); Arrays.fill(block._data, _default_fill);
return block; return block;
@ -230,4 +244,8 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock
public byte [] getData() { public byte [] getData() {
return _data; return _data;
} }
public POIFSBigBlockSize getBigBlockSize() {
return _bigBlockSize;
}
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -18,6 +18,8 @@
package org.apache.poi.poifs.filesystem; package org.apache.poi.poifs.filesystem;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -25,6 +27,9 @@ 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.storage.HeaderBlockReader;
import org.apache.poi.poifs.storage.RawDataBlockList;
/** /**
* Tests for POIFSFileSystem * Tests for POIFSFileSystem
@ -168,6 +173,34 @@ public final class TestPOIFSFileSystem extends TestCase {
assertTrue(msg.startsWith("Your file contains 695 sectors")); 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) { private static InputStream openSampleStream(String sampleFileName) {
return HSSFTestDataSamples.openSampleFileStream(sampleFileName); return HSSFTestDataSamples.openSampleFileStream(sampleFileName);

View File

@ -70,7 +70,7 @@ public final class TestPropertyTable extends TestCase {
public void testWriterPropertyTable() throws IOException { public void testWriterPropertyTable() throws IOException {
// create the PropertyTable // 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 // create three DocumentProperty instances and add them to the
// PropertyTable // PropertyTable
@ -430,15 +430,17 @@ public final class TestPropertyTable extends TestCase {
}; };
RawDataBlockList data_blocks = new RawDataBlockList(new ByteArrayInputStream(RawDataUtil 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 }; int[] bat_array = { 15 };
// need to initialize the block list with a block allocation // need to initialize the block list with a block allocation
// table // 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 // 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()); assertEquals(30 * 64, table.getRoot().getSize());
int count = 0; int count = 0;

View File

@ -38,7 +38,7 @@ public final class LocalRawDataBlockList extends RawDataBlockList {
public LocalRawDataBlockList() public LocalRawDataBlockList()
throws IOException 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>(); _list = new ArrayList<RawDataBlock>();
_array = null; _array = null;
} }

View File

@ -21,6 +21,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import org.apache.poi.poifs.common.POIFSConstants;
import junit.framework.TestCase; import junit.framework.TestCase;
/** /**
@ -39,27 +41,27 @@ public final class TestBATBlock extends TestCase {
public void testCreateBATBlocks() throws IOException { public void testCreateBATBlocks() throws IOException {
// test 0 length array (basic sanity) // 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); assertEquals(0, rvalue.length);
// test array of length 1 // 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); assertEquals(1, rvalue.length);
verifyContents(rvalue, 1); verifyContents(rvalue, 1);
// test array of length 127 // 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); assertEquals(1, rvalue.length);
verifyContents(rvalue, 127); verifyContents(rvalue, 127);
// test array of length 128 // 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); assertEquals(1, rvalue.length);
verifyContents(rvalue, 128); verifyContents(rvalue, 128);
// test array of length 129 // 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); assertEquals(2, rvalue.length);
verifyContents(rvalue, 129); verifyContents(rvalue, 129);
} }
@ -105,32 +107,32 @@ public final class TestBATBlock extends TestCase {
public void testCreateXBATBlocks() throws IOException { public void testCreateXBATBlocks() throws IOException {
// test 0 length array (basic sanity) // 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); assertEquals(0, rvalue.length);
// test array of length 1 // 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); assertEquals(1, rvalue.length);
verifyXBATContents(rvalue, 1, 1); verifyXBATContents(rvalue, 1, 1);
// test array of length 127 // 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); assertEquals(1, rvalue.length);
verifyXBATContents(rvalue, 127, 1); verifyXBATContents(rvalue, 127, 1);
// test array of length 128 // 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); assertEquals(2, rvalue.length);
verifyXBATContents(rvalue, 128, 1); verifyXBATContents(rvalue, 128, 1);
// test array of length 254 // 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); assertEquals(2, rvalue.length);
verifyXBATContents(rvalue, 254, 1); verifyXBATContents(rvalue, 254, 1);
// test array of length 255 // 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); assertEquals(3, rvalue.length);
verifyXBATContents(rvalue, 255, 1); verifyXBATContents(rvalue, 255, 1);
} }
@ -193,17 +195,17 @@ public final class TestBATBlock extends TestCase {
{ {
assertEquals( assertEquals(
"requirement for " + blockCounts[ j ], requirements[ j ], "requirement for " + blockCounts[ j ], requirements[ j ],
BATBlock.calculateXBATStorageRequirements(blockCounts[ j ])); BATBlock.calculateXBATStorageRequirements(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, blockCounts[ j ]));
} }
} }
public void testEntriesPerBlock() { public void testEntriesPerBlock() {
assertEquals(128, BATBlock.entriesPerBlock()); assertEquals(128, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS.getBATEntriesPerBlock());
} }
public void testEntriesPerXBATBlock() { public void testEntriesPerXBATBlock() {
assertEquals(127, BATBlock.entriesPerXBATBlock()); assertEquals(127, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS.getXBATEntriesPerBlock());
} }
public void testGetXBATChainOffset() { 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.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
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.util.HexRead; import org.apache.poi.util.HexRead;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
@ -187,8 +188,9 @@ public final class TestBlockAllocationTableReader extends TestCase {
sbts[j] = new RawDataBlock(sbt_input); sbts[j] = new RawDataBlock(sbt_input);
} }
SmallDocumentBlockList small_blocks = new SmallDocumentBlockList(SmallDocumentBlock SmallDocumentBlockList small_blocks = new SmallDocumentBlockList(SmallDocumentBlock
.extract(sbts)); .extract(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, sbts));
BlockAllocationTableReader sbat = new BlockAllocationTableReader(sbats, small_blocks); BlockAllocationTableReader sbat = new BlockAllocationTableReader(
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, sbats, small_blocks);
boolean[] isUsed = { boolean[] isUsed = {
false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
false, true, true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true,
@ -271,7 +273,8 @@ public final class TestBlockAllocationTableReader extends TestCase {
} }
list.fill(132); list.fill(132);
int[] blocks = { 2, 3 }; 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++) { for (int i = 0; i < (130 * 128); i++) {
if (i % 256 == 0) { if (i % 256 == 0) {
@ -353,7 +356,8 @@ public final class TestBlockAllocationTableReader extends TestCase {
list.add(new RawDataBlock(new ByteArrayInputStream(data))); list.add(new RawDataBlock(new ByteArrayInputStream(data)));
list.fill(1); list.fill(1);
int[] blocks = { 0 }; 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[] start_blocks = { -2, 1, 2, 3, 5, 7, 9, 11, 12 };
int[] expected_length = { 0, 1, -1, -1, -1, -1, -1, -1, 116 }; 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() { public void testBadSectorAllocationTableSize_bug48085() {
int BLOCK_SIZE = 512; 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 // 512 bytes take from the start of bugzilla attachment 24444
byte[] initData = HexRead.readFromString( byte[] initData = HexRead.readFromString(
@ -402,12 +409,13 @@ public final class TestBlockAllocationTableReader extends TestCase {
RawDataBlockList dataBlocks; RawDataBlockList dataBlocks;
try { try {
hb = new HeaderBlockReader(stream); hb = new HeaderBlockReader(stream);
dataBlocks = new RawDataBlockList(stream, BLOCK_SIZE); dataBlocks = new RawDataBlockList(stream, bigBlockSize);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
try { 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); hb.getXBATIndex(), dataBlocks);
} catch (IOException e) { } catch (IOException e) {
// expected during successful test // expected during successful test

View File

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

View File

@ -25,6 +25,7 @@ import java.util.List;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
@ -142,10 +143,10 @@ public final class TestBlockListImpl extends TestCase {
BlockListImpl list = create(); BlockListImpl list = create();
list.setBAT(null); list.setBAT(null);
list.setBAT(new BlockAllocationTableReader()); list.setBAT(new BlockAllocationTableReader(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS));
try try
{ {
list.setBAT(new BlockAllocationTableReader()); list.setBAT(new BlockAllocationTableReader(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS));
fail("second attempt should have failed"); fail("second attempt should have failed");
} }
catch (IOException ignored) catch (IOException ignored)
@ -233,7 +234,7 @@ public final class TestBlockListImpl extends TestCase {
0 0
}; };
BlockAllocationTableReader table = 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 = int[] start_blocks =
{ {
-2, 1, 2, 3, 5, 7, 9, 11, 12 -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.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import org.apache.poi.poifs.common.POIFSConstants;
import junit.framework.TestCase; import junit.framework.TestCase;
/** /**
@ -55,7 +57,7 @@ public final class TestDocumentBlock extends TestCase {
byte[] data = new byte[ Math.min(_testdata.length - index, 512) ]; byte[] data = new byte[ Math.min(_testdata.length - index, 512) ];
System.arraycopy(_testdata, index, data, 0, data.length); 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); verifyOutput(block, data);
size += block.size(); size += block.size();

View File

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

View File

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

View File

@ -51,14 +51,14 @@ public final class TestRawDataBlockList extends TestCase {
{ {
data[ j ] = ( byte ) j; 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 * Test creating an empty RawDataBlockList
*/ */
public void testEmptyConstructor() throws IOException { 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 // Check we logged the error
logger.reset(); 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()); 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 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 }; int[] bat_array = { 15 };
// need to initialize the block list with a block allocation // need to initialize the block list with a block allocation
// table // 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 // 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(); 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); assertNotNull(bl);
} }
} }

View File

@ -24,6 +24,7 @@ import java.util.List;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.POIFSDocument; import org.apache.poi.poifs.filesystem.POIFSDocument;
import org.apache.poi.poifs.property.PropertyTable; import org.apache.poi.poifs.property.PropertyTable;
import org.apache.poi.poifs.property.RootProperty; import org.apache.poi.poifs.property.RootProperty;
@ -74,9 +75,9 @@ public final class TestSmallBlockTableWriter extends TestCase {
documents documents
.add(new POIFSDocument("doc9", .add(new POIFSDocument("doc9",
new ByteArrayInputStream(new byte[ 9 ]))); new ByteArrayInputStream(new byte[ 9 ])));
RootProperty root = new PropertyTable().getRoot(); RootProperty root = new PropertyTable(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS).getRoot();
SmallBlockTableWriter sbtw = new SmallBlockTableWriter(documents, SmallBlockTableWriter sbtw = new SmallBlockTableWriter(
root); POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, documents,root);
BlockAllocationTableWriter bat = sbtw.getSBAT(); BlockAllocationTableWriter bat = sbtw.getSBAT();
// 15 small blocks: 6 for doc340, 0 for doc5000 (too big), 0 // 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.Iterator;
import java.util.List; import java.util.List;
import org.apache.poi.poifs.common.POIFSConstants;
import junit.framework.TestCase; import junit.framework.TestCase;
/** /**
@ -55,7 +57,7 @@ public final class TestSmallDocumentBlock extends TestCase {
while (true) while (true)
{ {
DocumentBlock block = new DocumentBlock(stream); DocumentBlock block = new DocumentBlock(stream,POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
documents.add(block); documents.add(block);
if (block.partiallyRead()) if (block.partiallyRead())
@ -65,7 +67,7 @@ public final class TestSmallDocumentBlock extends TestCase {
} }
SmallDocumentBlock[] results = SmallDocumentBlock[] results =
SmallDocumentBlock SmallDocumentBlock
.convert(( BlockWritable [] ) documents .convert(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,( BlockWritable [] ) documents
.toArray(new DocumentBlock[ 0 ]), _testdata_size); .toArray(new DocumentBlock[ 0 ]), _testdata_size);
assertEquals("checking correct result size: ", assertEquals("checking correct result size: ",
@ -108,8 +110,8 @@ public final class TestSmallDocumentBlock extends TestCase {
{ {
array[ k ] = ( byte ) k; array[ k ] = ( byte ) k;
} }
SmallDocumentBlock[] blocks = SmallDocumentBlock.convert(array, SmallDocumentBlock[] blocks = SmallDocumentBlock.convert(
319); POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, array, 319);
assertEquals(5, blocks.length); assertEquals(5, blocks.length);
ByteArrayOutputStream stream = new ByteArrayOutputStream(); ByteArrayOutputStream stream = new ByteArrayOutputStream();
@ -146,7 +148,7 @@ public final class TestSmallDocumentBlock extends TestCase {
{ {
foo.add(new Object()); 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 big block count: ", (j + 7) / 8, result);
assertEquals("correct small block count: ", 8 * result, assertEquals("correct small block count: ", 8 * result,
@ -206,7 +208,7 @@ public final class TestSmallDocumentBlock extends TestCase {
{ {
new RawDataBlock(new ByteArrayInputStream(data)) 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(); Iterator iter = output.iterator();
offset = 0; offset = 0;

View File

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