]> source.dussan.org Git - poi.git/commitdiff
Make a start on handling different big block sizes in POIFS, but work isn't complete...
authorNick Burch <nick@apache.org>
Thu, 13 Mar 2008 15:38:28 +0000 (15:38 +0000)
committerNick Burch <nick@apache.org>
Thu, 13 Mar 2008 15:38:28 +0000 (15:38 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@636786 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/poifs/common/POIFSConstants.java
src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java
src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
src/java/org/apache/poi/poifs/storage/HeaderBlockReader.java
src/java/org/apache/poi/poifs/storage/RawDataBlockList.java
src/testcases/org/apache/poi/poifs/property/TestPropertyTable.java
src/testcases/org/apache/poi/poifs/storage/LocalRawDataBlockList.java
src/testcases/org/apache/poi/poifs/storage/TestRawDataBlockList.java
src/testcases/org/apache/poi/poifs/storage/TestSmallBlockTableReader.java

index 399f52be4ba3e8ab39631675c8ed2e6bce794451..ff2050274dcf20cd10460a993db7da08b333c6c0 100644 (file)
@@ -27,7 +27,11 @@ package org.apache.poi.poifs.common;
 
 public interface POIFSConstants
 {
+    /** Most files use 512 bytes as their big block size */
     public static final int BIG_BLOCK_SIZE = 0x0200;
+    /** Some use 4096 bytes */
+    public static final int LARGER_BIG_BLOCK_SIZE = 0x1000;
+    
     public static final int END_OF_CHAIN   = -2;
     public static final int PROPERTY_SIZE  = 0x0080;
     public static final int UNUSED_BLOCK   = -1;
index fe94b4aaf9ebc7ba74965552791fe82b0f0399c0..73911e6b0e05c9e27cb7f04dbf55cdd865cfabb0 100644 (file)
@@ -78,7 +78,7 @@ public class POIFSReader
         HeaderBlockReader header_block_reader = new HeaderBlockReader(stream);
 
         // read the rest of the stream into blocks
-        RawDataBlockList  data_blocks         = new RawDataBlockList(stream);
+        RawDataBlockList  data_blocks         = new RawDataBlockList(stream, header_block_reader.getBigBlockSize());
 
         // set up the block allocation table (necessary for the
         // data_blocks to be manageable
index ef9acfe60b7cd669b1bdeeb50d49a2f901a442a4..61774dc6768e8a599a20196fa561218104578843 100644 (file)
@@ -33,6 +33,7 @@ import java.util.List;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.dev.POIFSViewable;
 import org.apache.poi.poifs.property.DirectoryProperty;
 import org.apache.poi.poifs.property.Property;
@@ -63,7 +64,6 @@ public class POIFSFileSystem
 {
     private static final Log _logger = LogFactory.getLog(POIFSFileSystem.class);
     
-    
     private static final class CloseIgnoringInputStream extends InputStream {
 
         private final InputStream _is;
@@ -91,11 +91,16 @@ public class POIFSFileSystem
     private PropertyTable _property_table;
     private List          _documents;
     private DirectoryNode _root;
+    
+    /**
+     * What big block size the file uses. Most files
+     *  use 512 bytes, but a few use 4096
+     */
+    private int bigBlockSize = POIFSConstants.BIG_BLOCK_SIZE;
 
     /**
      * Constructor, intended for writing
      */
-
     public POIFSFileSystem()
     {
         _property_table = new PropertyTable();
@@ -138,13 +143,15 @@ public class POIFSFileSystem
         this();
         boolean success = false;
 
-        // read the header block from the stream
         HeaderBlockReader header_block_reader;
-        // read the rest of the stream into blocks
         RawDataBlockList data_blocks;
         try {
+            // read the header block from the stream
             header_block_reader = new HeaderBlockReader(stream);
-            data_blocks = new RawDataBlockList(stream);
+            bigBlockSize = header_block_reader.getBigBlockSize();
+            
+            // read the rest of the stream into blocks
+            data_blocks = new RawDataBlockList(stream, bigBlockSize);
             success = true;
         } finally {
             closeInputStream(stream, success);
@@ -307,7 +314,7 @@ public class POIFSFileSystem
 
         // create a list of BATManaged objects: the documents plus the
         // property table and the small block table
-        List                       bm_objects = new ArrayList();
+        List bm_objects = new ArrayList();
 
         bm_objects.addAll(_documents);
         bm_objects.add(_property_table);
@@ -602,6 +609,13 @@ public class POIFSFileSystem
         return "POIFS FileSystem";
     }
 
+    /**
+     * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
+     */
+    public int getBigBlockSize() {
+       return bigBlockSize;
+    }
+    
     /* **********  END  begin implementation of POIFSViewable ********** */
 }   // end public class POIFSFileSystem
 
index 0d5bb817b4540c6e1e2b35ce23dd1df4ec08a402..b001b8105857f8fb61b2c170ddd8597b89d5ad4a 100644 (file)
@@ -21,8 +21,6 @@ package org.apache.poi.poifs.storage;
 
 import java.io.*;
 
-import java.util.*;
-
 import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
 import org.apache.poi.util.IOUtils;
@@ -30,7 +28,6 @@ import org.apache.poi.util.IntegerField;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianConsts;
 import org.apache.poi.util.LongField;
-import org.apache.poi.util.ShortField;
 
 /**
  * The block containing the archive header
@@ -41,6 +38,11 @@ import org.apache.poi.util.ShortField;
 public class HeaderBlockReader
     implements HeaderBlockConstants
 {
+    /**
+     * What big block size the file uses. Most files
+     *  use 512 bytes, but a few use 4096
+     */
+    private int bigBlockSize = POIFSConstants.BIG_BLOCK_SIZE;
 
     // number of big block allocation table blocks (int)
     private IntegerField _bat_count;
@@ -69,20 +71,27 @@ public class HeaderBlockReader
     public HeaderBlockReader(final InputStream stream)
         throws IOException
     {
-        _data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
-        int byte_count = IOUtils.readFully(stream, _data);
-
-        if (byte_count != POIFSConstants.BIG_BLOCK_SIZE)
-        {
-               if (byte_count == -1)
-                       //Cant have -1 bytes read in the error message!
-                       byte_count = 0;
-            String type = " byte" + ((byte_count == 1) ? ("")
-                                                       : ("s"));
-
-            throw new IOException("Unable to read entire header; "
-                                  + byte_count + type + " read; expected "
-                                  + POIFSConstants.BIG_BLOCK_SIZE + " bytes");
+       // At this point, we don't know how big our
+       //  block sizes are
+       // So, read the first 32 bytes to check, then
+       //  read the rest of the block
+       byte[] blockStart = new byte[32];
+       int bsCount = IOUtils.readFully(stream, blockStart);
+       if(bsCount != 32) {
+               alertShortRead(bsCount);
+       }
+       
+       // Figure out our block size
+       if(blockStart[30] == 12) {
+               bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE;
+       }
+        _data = new byte[ bigBlockSize ];
+        System.arraycopy(blockStart, 0, _data, 0, blockStart.length);
+       
+       // Now we can read the rest of our header
+        int byte_count = IOUtils.readFully(stream, _data, blockStart.length, _data.length - blockStart.length);
+        if (byte_count+bsCount != bigBlockSize) {
+               alertShortRead(byte_count);
         }
 
         // verify signature
@@ -110,13 +119,24 @@ public class HeaderBlockReader
         _xbat_start     = new IntegerField(_xbat_start_offset, _data);
         _xbat_count     = new IntegerField(_xbat_count_offset, _data);
     }
+    
+    private void alertShortRead(int read) throws IOException {
+       if (read == -1)
+               //Cant have -1 bytes read in the error message!
+               read = 0;
+        String type = " byte" + ((read == 1) ? ("")
+                                                   : ("s"));
+
+        throw new IOException("Unable to read entire header; "
+                              + read + type + " read; expected "
+                              + bigBlockSize + " bytes");
+    }
 
     /**
      * get start of Property Table
      *
      * @return the index of the first block of the Property Table
      */
-
     public int getPropertyStart()
     {
         return _property_start.get();
@@ -174,5 +194,12 @@ public class HeaderBlockReader
     {
         return _xbat_start.get();
     }
+    
+    /**
+     * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
+     */
+    public int getBigBlockSize() {
+       return bigBlockSize;
+    }
 }   // end public class HeaderBlockReader
 
index eed318fb552ae54ec2de5bce3c3891e0fe88c416..76ab219562007e692fee01b6b39f5553b6c11ee7 100644 (file)
@@ -37,19 +37,20 @@ public class RawDataBlockList
      * Constructor RawDataBlockList
      *
      * @param stream the InputStream from which the data will be read
+     * @param bigBlockSize The big block size, either 512 bytes or 4096 bytes
      *
      * @exception IOException on I/O errors, and if an incomplete
      *            block is read
      */
 
-    public RawDataBlockList(final InputStream stream)
+    public RawDataBlockList(final InputStream stream, int bigBlockSize)
         throws IOException
     {
         List blocks = new ArrayList();
 
         while (true)
         {
-            RawDataBlock block = new RawDataBlock(stream);
+            RawDataBlock block = new RawDataBlock(stream, bigBlockSize);
 
             if (block.eof())
             {
index 895c40f70441ea923d5af1641fbe3e81c71151ec..008504fb00311010f755e8b74158dfec296fa909 100644 (file)
@@ -25,6 +25,7 @@ import java.util.*;
 
 import junit.framework.*;
 
+import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.storage.BlockAllocationTableReader;
 import org.apache.poi.poifs.storage.RawDataBlockList;
 
@@ -2598,7 +2599,7 @@ public class TestPropertyTable
             ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF
         };
         RawDataBlockList data_blocks    =
-            new RawDataBlockList(new ByteArrayInputStream(raw_data_array));
+            new RawDataBlockList(new ByteArrayInputStream(raw_data_array), POIFSConstants.BIG_BLOCK_SIZE);
         int[]            bat_array      =
         {
             15
index ed3e8d925996dda7e8dd4373405b6c3200e34c20..21049ebf1816bdc9c76475031a4bda4c886f457e 100644 (file)
@@ -19,6 +19,8 @@
 
 package org.apache.poi.poifs.storage;
 
+import org.apache.poi.poifs.common.POIFSConstants;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianConsts;
 
@@ -47,7 +49,7 @@ public class LocalRawDataBlockList
     public LocalRawDataBlockList()
         throws IOException
     {
-        super(new ByteArrayInputStream(new byte[ 0 ]));
+        super(new ByteArrayInputStream(new byte[ 0 ]), POIFSConstants.BIG_BLOCK_SIZE);
         _list  = new ArrayList();
         _array = null;
     }
index ac6fc08c052a503013a8ad0a04ab267c5fc19a11..d151029762089e1634a46b4ff9fadddc9643bc93 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.poi.poifs.storage;
 
 import java.io.*;
 
+import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.util.DummyPOILogger;
 import org.apache.poi.util.POILogFactory;
 
@@ -69,7 +70,7 @@ public class TestRawDataBlockList
         {
             data[ j ] = ( byte ) j;
         }
-        new RawDataBlockList(new ByteArrayInputStream(data));
+        new RawDataBlockList(new ByteArrayInputStream(data), POIFSConstants.BIG_BLOCK_SIZE);
     }
 
     /**
@@ -81,7 +82,7 @@ public class TestRawDataBlockList
     public void testEmptyConstructor()
         throws IOException
     {
-        new RawDataBlockList(new ByteArrayInputStream(new byte[ 0 ]));
+        new RawDataBlockList(new ByteArrayInputStream(new byte[ 0 ]), POIFSConstants.BIG_BLOCK_SIZE);
     }
 
     /**
@@ -108,7 +109,7 @@ public class TestRawDataBlockList
 
             // Check we logged the error
             logger.reset();
-            new RawDataBlockList(new ByteArrayInputStream(data));
+            new RawDataBlockList(new ByteArrayInputStream(data), POIFSConstants.BIG_BLOCK_SIZE);
             assertEquals(1, logger.logged.size());
         }
     }
index bb2e3c4c0e63e5dac85a3ec6c161750afce63cc4..4d4254a91e4661fb02d83a065840518f8319cd30 100644 (file)
@@ -25,6 +25,7 @@ import java.util.*;
 
 import junit.framework.*;
 
+import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.property.PropertyTable;
 import org.apache.poi.poifs.property.RootProperty;
 
@@ -2112,7 +2113,7 @@ public class TestSmallBlockTableReader
             ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF
         };
         RawDataBlockList data_blocks    =
-            new RawDataBlockList(new ByteArrayInputStream(raw_data_array));
+            new RawDataBlockList(new ByteArrayInputStream(raw_data_array), POIFSConstants.BIG_BLOCK_SIZE);
         int[]            bat_array      =
         {
             15