diff options
author | Nick Burch <nick@apache.org> | 2008-11-12 18:25:33 +0000 |
---|---|---|
committer | Nick Burch <nick@apache.org> | 2008-11-12 18:25:33 +0000 |
commit | 1b24850c7cd4251a35ad39a41195da134b194416 (patch) | |
tree | aa0e32123465a3d731d7994af58f1ab138123d98 /src/java/org/apache/poi | |
parent | 84d10b7ecd5956e5deaa1e9a10903c2921f97f46 (diff) | |
download | poi-1b24850c7cd4251a35ad39a41195da134b194416.tar.gz poi-1b24850c7cd4251a35ad39a41195da134b194416.zip |
Fix bug #45290 - Support odd files where the POIFS header block comes after the data blocks, and is on the data blocks list
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@713447 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/poi')
7 files changed, 55 insertions, 27 deletions
diff --git a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java index 73911e6b0e..6a1423ea48 100644 --- a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java +++ b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java @@ -245,13 +245,13 @@ public class POIFSReader { document = new POIFSDocument(name, small_blocks - .fetchBlocks(startBlock), size); + .fetchBlocks(startBlock, -1), size); } else { document = new POIFSDocument(name, big_blocks - .fetchBlocks(startBlock), size); + .fetchBlocks(startBlock, -1), size); } while (listeners.hasNext()) { @@ -270,11 +270,11 @@ public class POIFSReader // consume the document's data and discard it if (property.shouldUseSmallBlocks()) { - small_blocks.fetchBlocks(startBlock); + small_blocks.fetchBlocks(startBlock, -1); } else { - big_blocks.fetchBlocks(startBlock); + big_blocks.fetchBlocks(startBlock, -1); } } } diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java index 92348ceaff..6ea37ea387 100644 --- a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java +++ b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java @@ -173,11 +173,16 @@ public class POIFSFileSystem data_blocks); // init documents - processProperties(SmallBlockTableReader - .getSmallDocumentBlocks(data_blocks, properties - .getRoot(), header_block_reader - .getSBATStart()), data_blocks, properties.getRoot() - .getChildren(), null); + processProperties( + SmallBlockTableReader.getSmallDocumentBlocks( + data_blocks, properties.getRoot(), + header_block_reader.getSBATStart() + ), + data_blocks, + properties.getRoot().getChildren(), + null, + header_block_reader.getPropertyStart() + ); } /** * @param stream the stream to be closed @@ -491,7 +496,8 @@ public class POIFSFileSystem private void processProperties(final BlockList small_blocks, final BlockList big_blocks, final Iterator properties, - final DirectoryNode dir) + final DirectoryNode dir, + final int headerPropertiesStartAt) throws IOException { while (properties.hasNext()) @@ -511,7 +517,8 @@ public class POIFSFileSystem processProperties( small_blocks, big_blocks, - (( DirectoryProperty ) property).getChildren(), new_dir); + (( DirectoryProperty ) property).getChildren(), + new_dir, headerPropertiesStartAt); } else { @@ -522,14 +529,15 @@ public class POIFSFileSystem if (property.shouldUseSmallBlocks()) { document = - new POIFSDocument(name, small_blocks - .fetchBlocks(startBlock), size); + new POIFSDocument(name, + small_blocks.fetchBlocks(startBlock, headerPropertiesStartAt), + size); } else { document = new POIFSDocument(name, - big_blocks.fetchBlocks(startBlock), + big_blocks.fetchBlocks(startBlock, headerPropertiesStartAt), size); } parent.createDocument(document); diff --git a/src/java/org/apache/poi/poifs/property/PropertyTable.java b/src/java/org/apache/poi/poifs/property/PropertyTable.java index 11c56e886d..00b306b792 100644 --- a/src/java/org/apache/poi/poifs/property/PropertyTable.java +++ b/src/java/org/apache/poi/poifs/property/PropertyTable.java @@ -78,7 +78,7 @@ public class PropertyTable _blocks = null; _properties = PropertyFactory - .convertToProperties(blockList.fetchBlocks(startBlock)); + .convertToProperties(blockList.fetchBlocks(startBlock, -1)); populatePropertyTree(( DirectoryProperty ) _properties.get(0)); } diff --git a/src/java/org/apache/poi/poifs/storage/BlockAllocationTableReader.java b/src/java/org/apache/poi/poifs/storage/BlockAllocationTableReader.java index b167d2fca1..1016db9c46 100644 --- a/src/java/org/apache/poi/poifs/storage/BlockAllocationTableReader.java +++ b/src/java/org/apache/poi/poifs/storage/BlockAllocationTableReader.java @@ -179,17 +179,34 @@ public class BlockAllocationTableReader */ ListManagedBlock [] fetchBlocks(final int startBlock, + final int headerPropertiesStartBlock, final BlockList blockList) throws IOException { List blocks = new ArrayList(); int currentBlock = startBlock; - - while (currentBlock != POIFSConstants.END_OF_CHAIN) - { - blocks.add(blockList.remove(currentBlock)); - currentBlock = _entries.get(currentBlock); + boolean firstPass = true; + + // Process the chain from the start to the end + // Normally we have header, data, end + // Sometimes we have data, header, end + // For those cases, stop at the header, not the end + while (currentBlock != POIFSConstants.END_OF_CHAIN) { + try { + blocks.add(blockList.remove(currentBlock)); + currentBlock = _entries.get(currentBlock); + } catch(IOException e) { + if(currentBlock == headerPropertiesStartBlock) { + // Special case where things are in the wrong order + System.err.println("Warning, header block comes after data blocks in POIFS block listing"); + currentBlock = POIFSConstants.END_OF_CHAIN; + } else { + // Ripple up + throw e; + } + } } + return ( ListManagedBlock [] ) blocks .toArray(new ListManagedBlock[ 0 ]); } diff --git a/src/java/org/apache/poi/poifs/storage/BlockList.java b/src/java/org/apache/poi/poifs/storage/BlockList.java index 2352d3a2c1..a5eb7df217 100644 --- a/src/java/org/apache/poi/poifs/storage/BlockList.java +++ b/src/java/org/apache/poi/poifs/storage/BlockList.java @@ -59,13 +59,14 @@ public interface BlockList * blocks are removed from the list. * * @param startBlock the index of the first block in the stream + * @param headerPropertiesStartBlock the index of the first header block in the stream * * @return the stream as an array of correctly ordered blocks * * @exception IOException if blocks are missing */ - public ListManagedBlock [] fetchBlocks(final int startBlock) + public ListManagedBlock [] fetchBlocks(final int startBlock, final int headerPropertiesStartBlock) throws IOException; /** diff --git a/src/java/org/apache/poi/poifs/storage/BlockListImpl.java b/src/java/org/apache/poi/poifs/storage/BlockListImpl.java index 7e44fda3f3..f315b5d515 100644 --- a/src/java/org/apache/poi/poifs/storage/BlockListImpl.java +++ b/src/java/org/apache/poi/poifs/storage/BlockListImpl.java @@ -94,8 +94,10 @@ class BlockListImpl result = _blocks[ index ]; if (result == null) { - throw new IOException("block[ " + index - + " ] already removed"); + throw new IOException( + "block[ " + index + " ] already removed - " + + "does your POIFS have circular or duplicate block references?" + ); } _blocks[ index ] = null; } @@ -119,7 +121,7 @@ class BlockListImpl * @exception IOException if blocks are missing */ - public ListManagedBlock [] fetchBlocks(final int startBlock) + public ListManagedBlock [] fetchBlocks(final int startBlock, final int headerPropertiesStartBlock) throws IOException { if (_bat == null) @@ -127,7 +129,7 @@ class BlockListImpl throw new IOException( "Improperly initialized list: no block allocation table provided"); } - return _bat.fetchBlocks(startBlock, this); + return _bat.fetchBlocks(startBlock, headerPropertiesStartBlock, this); } /** diff --git a/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java b/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java index e70774aa16..4da79e71f1 100644 --- a/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java +++ b/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java @@ -56,9 +56,9 @@ public class SmallBlockTableReader { BlockList list = new SmallDocumentBlockList(SmallDocumentBlock - .extract(blockList.fetchBlocks(root.getStartBlock()))); + .extract(blockList.fetchBlocks(root.getStartBlock(), -1))); - new BlockAllocationTableReader(blockList.fetchBlocks(sbatStart), + new BlockAllocationTableReader(blockList.fetchBlocks(sbatStart, -1), list); return list; } |