Save This Page
Home » poi-src-3.2-FINAL-20081019 » org.apache.poi.poifs » storage » [javadoc | source]
    1   
    2   /* ====================================================================
    3      Licensed to the Apache Software Foundation (ASF) under one or more
    4      contributor license agreements.  See the NOTICE file distributed with
    5      this work for additional information regarding copyright ownership.
    6      The ASF licenses this file to You under the Apache License, Version 2.0
    7      (the "License"); you may not use this file except in compliance with
    8      the License.  You may obtain a copy of the License at
    9   
   10          http://www.apache.org/licenses/LICENSE-2.0
   11   
   12      Unless required by applicable law or agreed to in writing, software
   13      distributed under the License is distributed on an "AS IS" BASIS,
   14      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15      See the License for the specific language governing permissions and
   16      limitations under the License.
   17   ==================================================================== */
   18           
   19   
   20   package org.apache.poi.poifs.storage;
   21   
   22   import java.io;
   23   
   24   import org.apache.poi.poifs.common.POIFSConstants;
   25   import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
   26   import org.apache.poi.util.IOUtils;
   27   import org.apache.poi.util.IntegerField;
   28   import org.apache.poi.util.LittleEndian;
   29   import org.apache.poi.util.LittleEndianConsts;
   30   import org.apache.poi.util.LongField;
   31   
   32   /**
   33    * The block containing the archive header
   34    *
   35    * @author Marc Johnson (mjohnson at apache dot org)
   36    */
   37   
   38   public class HeaderBlockReader
   39       implements HeaderBlockConstants
   40   {
   41       /**
   42        * What big block size the file uses. Most files
   43        *  use 512 bytes, but a few use 4096
   44        */
   45       private int bigBlockSize = POIFSConstants.BIG_BLOCK_SIZE;
   46   
   47       // number of big block allocation table blocks (int)
   48       private IntegerField _bat_count;
   49   
   50       // start of the property set block (int index of the property set
   51       // chain's first big block)
   52       private IntegerField _property_start;
   53   
   54       // start of the small block allocation table (int index of small
   55       // block allocation table's first big block)
   56       private IntegerField _sbat_start;
   57   
   58       // big block index for extension to the big block allocation table
   59       private IntegerField _xbat_start;
   60       private IntegerField _xbat_count;
   61       private byte[]       _data;
   62   
   63       /**
   64        * create a new HeaderBlockReader from an InputStream
   65        *
   66        * @param stream the source InputStream
   67        *
   68        * @exception IOException on errors or bad data
   69        */
   70   
   71       public HeaderBlockReader(final InputStream stream)
   72           throws IOException
   73       {
   74       	// At this point, we don't know how big our
   75       	//  block sizes are
   76       	// So, read the first 32 bytes to check, then
   77       	//  read the rest of the block
   78       	byte[] blockStart = new byte[32];
   79       	int bsCount = IOUtils.readFully(stream, blockStart);
   80       	if(bsCount != 32) {
   81       		alertShortRead(bsCount);
   82       	}
   83       	
   84       	// Figure out our block size
   85       	if(blockStart[30] == 12) {
   86       		bigBlockSize = POIFSConstants.LARGER_BIG_BLOCK_SIZE;
   87       	}
   88           _data = new byte[ bigBlockSize ];
   89           System.arraycopy(blockStart, 0, _data, 0, blockStart.length);
   90       	
   91       	// Now we can read the rest of our header
   92           int byte_count = IOUtils.readFully(stream, _data, blockStart.length, _data.length - blockStart.length);
   93           if (byte_count+bsCount != bigBlockSize) {
   94       		alertShortRead(byte_count);
   95           }
   96   
   97           // verify signature
   98           LongField signature = new LongField(_signature_offset, _data);
   99   
  100           if (signature.get() != _signature)
  101           {
  102   			// Is it one of the usual suspects?
  103           	byte[] OOXML_FILE_HEADER = POIFSConstants.OOXML_FILE_HEADER;
  104   			if(_data[0] == OOXML_FILE_HEADER[0] && 
  105   					_data[1] == OOXML_FILE_HEADER[1] && 
  106   					_data[2] == OOXML_FILE_HEADER[2] &&
  107   					_data[3] == OOXML_FILE_HEADER[3]) {
  108   				throw new OfficeXmlFileException("The supplied data appears to be in the Office 2007+ XML. POI only supports OLE2 Office documents");
  109   			}
  110   
  111   			// Give a generic error
  112               throw new IOException("Invalid header signature; read "
  113                                     + signature.get() + ", expected "
  114                                     + _signature);
  115           }
  116           _bat_count      = new IntegerField(_bat_count_offset, _data);
  117           _property_start = new IntegerField(_property_start_offset, _data);
  118           _sbat_start     = new IntegerField(_sbat_start_offset, _data);
  119           _xbat_start     = new IntegerField(_xbat_start_offset, _data);
  120           _xbat_count     = new IntegerField(_xbat_count_offset, _data);
  121       }
  122       
  123       private void alertShortRead(int read) throws IOException {
  124       	if (read == -1)
  125       		//Cant have -1 bytes read in the error message!
  126       		read = 0;
  127           String type = " byte" + ((read == 1) ? ("")
  128                                                      : ("s"));
  129   
  130           throw new IOException("Unable to read entire header; "
  131                                 + read + type + " read; expected "
  132                                 + bigBlockSize + " bytes");
  133       }
  134   
  135       /**
  136        * get start of Property Table
  137        *
  138        * @return the index of the first block of the Property Table
  139        */
  140       public int getPropertyStart()
  141       {
  142           return _property_start.get();
  143       }
  144   
  145       /**
  146        * @return start of small block allocation table
  147        */
  148   
  149       public int getSBATStart()
  150       {
  151           return _sbat_start.get();
  152       }
  153   
  154       /**
  155        * @return number of BAT blocks
  156        */
  157   
  158       public int getBATCount()
  159       {
  160           return _bat_count.get();
  161       }
  162   
  163       /**
  164        * @return BAT array
  165        */
  166   
  167       public int [] getBATArray()
  168       {
  169           int[] result = new int[ _max_bats_in_header ];
  170           int   offset = _bat_array_offset;
  171   
  172           for (int j = 0; j < _max_bats_in_header; j++)
  173           {
  174               result[ j ] = LittleEndian.getInt(_data, offset);
  175               offset      += LittleEndianConsts.INT_SIZE;
  176           }
  177           return result;
  178       }
  179   
  180       /**
  181        * @return XBAT count
  182        */
  183   
  184       public int getXBATCount()
  185       {
  186           return _xbat_count.get();
  187       }
  188   
  189       /**
  190        * @return XBAT index
  191        */
  192   
  193       public int getXBATIndex()
  194       {
  195           return _xbat_start.get();
  196       }
  197       
  198       /**
  199        * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
  200        */
  201       public int getBigBlockSize() {
  202       	return bigBlockSize;
  203       }
  204   }   // end public class HeaderBlockReader
  205   

Save This Page
Home » poi-src-3.2-FINAL-20081019 » org.apache.poi.poifs » storage » [javadoc | source]