Improved error message when attempting to read BIFF2 file (bugzilla 46269)

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@721620 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-11-29 03:12:39 +00:00
parent 5f3c3d71a3
commit 886de704ff
3 changed files with 156 additions and 147 deletions

View File

@ -37,6 +37,7 @@
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.5-beta5" date="2008-??-??"> <release version="3.5-beta5" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">46269 - Improved error message when attempting to read BIFF2 file</action>
<action dev="POI-DEVELOPERS" type="fix">46206 - Fixed Sheet to tolerate missing DIMENSION records</action> <action dev="POI-DEVELOPERS" type="fix">46206 - Fixed Sheet to tolerate missing DIMENSION records</action>
<action dev="POI-DEVELOPERS" type="add">46301 - added pivot table records: SXDI, SXVDEX, SXPI, SXIDSTM, SXVIEW, SXVD, SXVS, et al</action> <action dev="POI-DEVELOPERS" type="add">46301 - added pivot table records: SXDI, SXVDEX, SXPI, SXIDSTM, SXVIEW, SXVD, SXVS, et al</action>
<action dev="POI-DEVELOPERS" type="fix">46280 - Fixed RowRecordsAggregate etc to properly skip PivotTable records</action> <action dev="POI-DEVELOPERS" type="fix">46280 - Fixed RowRecordsAggregate etc to properly skip PivotTable records</action>

View File

@ -34,6 +34,7 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.5-beta5" date="2008-??-??"> <release version="3.5-beta5" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">46269 - Improved error message when attempting to read BIFF2 file</action>
<action dev="POI-DEVELOPERS" type="fix">46206 - Fixed Sheet to tolerate missing DIMENSION records</action> <action dev="POI-DEVELOPERS" type="fix">46206 - Fixed Sheet to tolerate missing DIMENSION records</action>
<action dev="POI-DEVELOPERS" type="add">46301 - added pivot table records: SXDI, SXVDEX, SXPI, SXIDSTM, SXVIEW, SXVD, SXVS, et al</action> <action dev="POI-DEVELOPERS" type="add">46301 - added pivot table records: SXDI, SXVDEX, SXPI, SXIDSTM, SXVIEW, SXVD, SXVS, et al</action>
<action dev="POI-DEVELOPERS" type="fix">46280 - Fixed RowRecordsAggregate etc to properly skip PivotTable records</action> <action dev="POI-DEVELOPERS" type="fix">46280 - Fixed RowRecordsAggregate etc to properly skip PivotTable records</action>

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
@ -16,48 +15,56 @@
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.poifs.storage; package org.apache.poi.poifs.storage;
import java.io.*; import static org.apache.poi.poifs.storage.HeaderBlockConstants._bat_array_offset;
import static org.apache.poi.poifs.storage.HeaderBlockConstants._bat_count_offset;
import static org.apache.poi.poifs.storage.HeaderBlockConstants._max_bats_in_header;
import static org.apache.poi.poifs.storage.HeaderBlockConstants._property_start_offset;
import static org.apache.poi.poifs.storage.HeaderBlockConstants._sbat_start_offset;
import static org.apache.poi.poifs.storage.HeaderBlockConstants._signature;
import static org.apache.poi.poifs.storage.HeaderBlockConstants._signature_offset;
import static org.apache.poi.poifs.storage.HeaderBlockConstants._xbat_count_offset;
import static org.apache.poi.poifs.storage.HeaderBlockConstants._xbat_start_offset;
import java.io.IOException;
import java.io.InputStream;
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.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.IntegerField;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LongField;
/** /**
* The block containing the archive header * The block containing the archive header
* *
* @author Marc Johnson (mjohnson at apache dot org) * @author Marc Johnson (mjohnson at apache dot org)
*/ */
public final class HeaderBlockReader {
public class HeaderBlockReader
implements HeaderBlockConstants
{
/** /**
* 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 int bigBlockSize = POIFSConstants.BIG_BLOCK_SIZE;
// number of big block allocation table blocks (int) /** number of big block allocation table blocks (int) */
private IntegerField _bat_count; private int _bat_count;
// start of the property set block (int index of the property set /** start of the property set block (int index of the property set
// chain's first big block) * chain's first big block)
private IntegerField _property_start; */
private int _property_start;
// start of the small block allocation table (int index of small /** start of the small block allocation table (int index of small
// block allocation table's first big block) * block allocation table's first big block)
private IntegerField _sbat_start; */
private int _sbat_start;
// big block index for extension to the big block allocation table /** big block index for extension to the big block allocation table */
private IntegerField _xbat_start; private int _xbat_start;
private IntegerField _xbat_count; private int _xbat_count;
private byte[] _data; private byte[] _data;
/** /**
@ -67,10 +74,7 @@ public class HeaderBlockReader
* *
* @exception IOException on errors or bad data * @exception IOException on errors or bad data
*/ */
public HeaderBlockReader(InputStream stream) throws IOException {
public HeaderBlockReader(final InputStream stream)
throws IOException
{
// At this point, we don't know how big our // At this point, we don't know how big our
// block sizes are // block sizes are
// So, read the first 32 bytes to check, then // So, read the first 32 bytes to check, then
@ -95,10 +99,9 @@ public class HeaderBlockReader
} }
// verify signature // verify signature
LongField signature = new LongField(_signature_offset, _data); long signature = LittleEndian.getLong(_data, _signature_offset);
if (signature.get() != _signature) if (signature != _signature) {
{
// Is it one of the usual suspects? // Is it one of the usual suspects?
byte[] OOXML_FILE_HEADER = POIFSConstants.OOXML_FILE_HEADER; byte[] OOXML_FILE_HEADER = POIFSConstants.OOXML_FILE_HEADER;
if(_data[0] == OOXML_FILE_HEADER[0] && if(_data[0] == OOXML_FILE_HEADER[0] &&
@ -107,25 +110,41 @@ public class HeaderBlockReader
_data[3] == OOXML_FILE_HEADER[3]) { _data[3] == OOXML_FILE_HEADER[3]) {
throw new OfficeXmlFileException("The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)"); throw new OfficeXmlFileException("The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)");
} }
if ((signature & 0xFF8FFFFFFFFFFFFFL) == 0x0010000200040009L) {
// BIFF2 raw stream starts with BOF (sid=0x0009, size=0x0004, data=0x00t0)
throw new IllegalArgumentException("The supplied data appears to be in BIFF2 format. "
+ "POI only supports BIFF8 format");
}
// Give a generic error // Give a generic error
throw new IOException("Invalid header signature; read " throw new IOException("Invalid header signature; read "
+ signature.get() + ", expected " + longToHex(signature) + ", expected "
+ _signature); + longToHex(_signature));
} }
_bat_count = new IntegerField(_bat_count_offset, _data); _bat_count = getInt(_bat_count_offset, _data);
_property_start = new IntegerField(_property_start_offset, _data); _property_start = getInt(_property_start_offset, _data);
_sbat_start = new IntegerField(_sbat_start_offset, _data); _sbat_start = getInt(_sbat_start_offset, _data);
_xbat_start = new IntegerField(_xbat_start_offset, _data); _xbat_start = getInt(_xbat_start_offset, _data);
_xbat_count = new IntegerField(_xbat_count_offset, _data); _xbat_count = getInt(_xbat_count_offset, _data);
} }
private void alertShortRead(int read) throws IOException { private static int getInt(int offset, byte[] data) {
if (read == -1) return LittleEndian.getInt(data, offset);
//Cant have -1 bytes read in the error message! }
private static String longToHex(long value) {
return new String(HexDump.longToHex(value));
}
private void alertShortRead(int pRead) throws IOException {
int read;
if (pRead < 0) {
//Can't have -1 bytes read in the error message!
read = 0; read = 0;
String type = " byte" + ((read == 1) ? ("") } else {
: ("s")); read = pRead;
}
String type = " byte" + (read == 1 ? (""): ("s"));
throw new IOException("Unable to read entire header; " throw new IOException("Unable to read entire header; "
+ read + type + " read; expected " + read + type + " read; expected "
@ -137,40 +156,32 @@ public class HeaderBlockReader
* *
* @return the index of the first block of the Property Table * @return the index of the first block of the Property Table
*/ */
public int getPropertyStart() public int getPropertyStart() {
{ return _property_start;
return _property_start.get();
} }
/** /**
* @return start of small block allocation table * @return start of small block allocation table
*/ */
public int getSBATStart() {
public int getSBATStart() return _sbat_start;
{
return _sbat_start.get();
} }
/** /**
* @return number of BAT blocks * @return number of BAT blocks
*/ */
public int getBATCount() {
public int getBATCount() return _bat_count;
{
return _bat_count.get();
} }
/** /**
* @return BAT array * @return BAT array
*/ */
public int[] getBATArray() {
public int [] getBATArray()
{
int[] result = new int[ _max_bats_in_header ]; int[] result = new int[ _max_bats_in_header ];
int offset = _bat_array_offset; int offset = _bat_array_offset;
for (int j = 0; j < _max_bats_in_header; j++) for (int j = 0; j < _max_bats_in_header; j++) {
{
result[ j ] = LittleEndian.getInt(_data, offset); result[ j ] = LittleEndian.getInt(_data, offset);
offset += LittleEndianConsts.INT_SIZE; offset += LittleEndianConsts.INT_SIZE;
} }
@ -180,19 +191,15 @@ public class HeaderBlockReader
/** /**
* @return XBAT count * @return XBAT count
*/ */
public int getXBATCount() {
public int getXBATCount() return _xbat_count;
{
return _xbat_count.get();
} }
/** /**
* @return XBAT index * @return XBAT index
*/ */
public int getXBATIndex() {
public int getXBATIndex() return _xbat_start;
{
return _xbat_start.get();
} }
/** /**
@ -201,5 +208,5 @@ public class HeaderBlockReader
public int getBigBlockSize() { public int getBigBlockSize() {
return bigBlockSize; return bigBlockSize;
} }
} // end public class HeaderBlockReader }