* The block containing the archive header
*/
public final class HeaderBlock implements HeaderBlockConstants {
- /**
+ private static final byte[] MAGIC_BIFF2 = {
+ 0x09, 0x00, // sid=0x0009
+ 0x04, 0x00, // size=0x0004
+ 0x00, 0x00, // unused
+ 0x70, 0x00 // 0x70 = multiple values
+ };
+
+ private static final byte[] MAGIC_BIFF3 = {
+ 0x09, 0x02, // sid=0x0209
+ 0x06, 0x00, // size=0x0006
+ 0x00, 0x00, // unused
+ 0x70, 0x00 // 0x70 = multiple values
+ };
+
+ private static final byte[] MAGIC_BIFF4a = {
+ 0x09, 0x04, // sid=0x0409
+ 0x06, 0x00, // size=0x0006
+ 0x00, 0x00, // unused
+ 0x70, 0x00 // 0x70 = multiple values
+ };
+
+ private static final byte[] MAGIC_BIFF4b = {
+ 0x09, 0x04, // sid=0x0409
+ 0x06, 0x00, // size=0x0006
+ 0x00, 0x00, // unused
+ 0x00, 0x01
+ };
+
+ private static final byte _default_value = ( byte ) 0xFF;
+
+ /**
* What big block size the file uses. Most files
* use 512 bytes, but a few use 4096
*/
*/
private final byte[] _data;
- private static final byte _default_value = ( byte ) 0xFF;
-
/**
* create a new HeaderBlockReader from an InputStream
*
*/
public HeaderBlock(InputStream stream) throws IOException {
// Grab the first 512 bytes
- // (For 4096 sized blocks, the remaining 3584 bytes are zero)
+ // (For 4096 sized blocks, the remaining 3584 bytes are zero)
// Then, process the contents
this(readFirst512(stream));
}
private HeaderBlock(byte[] data) throws IOException {
- this._data = data;
+ this._data = data.clone();
// verify signature
long signature = LittleEndian.getLong(_data, _signature_offset);
if (signature != _signature) {
// Is it one of the usual suspects?
- byte[] OOXML_FILE_HEADER = POIFSConstants.OOXML_FILE_HEADER;
- if (_data[0] == OOXML_FILE_HEADER[0] &&
- _data[1] == OOXML_FILE_HEADER[1] &&
- _data[2] == OOXML_FILE_HEADER[2] &&
- _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)");
+ if (cmp(POIFSConstants.OOXML_FILE_HEADER, data)) {
+ 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)");
}
- byte[] RAW_XML_FILE_HEADER = POIFSConstants.RAW_XML_FILE_HEADER;
- if (_data[0] == RAW_XML_FILE_HEADER[0] &&
- _data[1] == RAW_XML_FILE_HEADER[1] &&
- _data[2] == RAW_XML_FILE_HEADER[2] &&
- _data[3] == RAW_XML_FILE_HEADER[3] &&
- _data[4] == RAW_XML_FILE_HEADER[4]) {
- throw new NotOLE2FileException("The supplied data appears to be a raw XML file. Formats such as Office 2003 XML are not supported");
+ if (cmp(POIFSConstants.RAW_XML_FILE_HEADER, data)) {
+ throw new NotOLE2FileException("The supplied data appears to be a raw XML file. "
+ + "Formats such as Office 2003 XML are not supported");
}
- if (_data[0] == 0x09 && _data[1] == 0x00 && // sid=0x0009
- _data[2] == 0x04 && _data[3] == 0x00 && // size=0x0004
- _data[4] == 0x00 && _data[5] == 0x00 && // unused
- (_data[6] == 0x10 || _data[6] == 0x20 || _data[6] == 0x40) &&
- _data[7] == 0x00) {
- // BIFF2 raw stream
- throw new OldExcelFormatException("The supplied data appears to be in BIFF2 format. " +
- "HSSF only supports the BIFF8 format, try OldExcelExtractor");
+ // BIFF2 raw stream
+ if (cmp(MAGIC_BIFF2, data)) {
+ throw new OldExcelFormatException("The supplied data appears to be in BIFF2 format. "
+ + "HSSF only supports the BIFF8 format, try OldExcelExtractor");
}
- if (_data[0] == 0x09 && _data[1] == 0x02 && // sid=0x0209
- _data[2] == 0x06 && _data[3] == 0x00 && // size=0x0006
- _data[4] == 0x00 && _data[5] == 0x00 && // unused
- (_data[6] == 0x10 || _data[6] == 0x20 || _data[6] == 0x40) &&
- _data[7] == 0x00) {
- // BIFF3 raw stream
- throw new OldExcelFormatException("The supplied data appears to be in BIFF3 format. " +
- "HSSF only supports the BIFF8 format, try OldExcelExtractor");
+
+ // BIFF3 raw stream
+ if (cmp(MAGIC_BIFF3, data)) {
+ throw new OldExcelFormatException("The supplied data appears to be in BIFF3 format. "
+ + "HSSF only supports the BIFF8 format, try OldExcelExtractor");
}
- if (_data[0] == 0x09 && _data[1] == 0x04 && // sid=0x0409
- _data[2] == 0x06 && _data[3] == 0x00 && // size=0x0006
- _data[4] == 0x00 && _data[5] == 0x00) { // unused
- if (((_data[6] == 0x10 || _data[6] == 0x20 || _data[6] == 0x40) &&
- _data[7] == 0x00) ||
- (_data[6] == 0x00 && _data[7] == 0x01)) {
- // BIFF4 raw stream
- throw new OldExcelFormatException("The supplied data appears to be in BIFF4 format. " +
- "HSSF only supports the BIFF8 format, try OldExcelExtractor");
- }
+
+ // BIFF4 raw stream
+ if (cmp(MAGIC_BIFF4a, data) || cmp(MAGIC_BIFF4b, data)) {
+ throw new OldExcelFormatException("The supplied data appears to be in BIFF4 format. "
+ + "HSSF only supports the BIFF8 format, try OldExcelExtractor");
}
// Give a generic error if the OLE2 signature isn't found
}
// Setup the fields to read and write the counts and starts
- _bat_count = new IntegerField(_bat_count_offset, data).get();
+ _bat_count = new IntegerField(_bat_count_offset, data).get();
_property_start = new IntegerField(_property_start_offset,_data).get();
_sbat_start = new IntegerField(_sbat_start_offset, _data).get();
_sbat_count = new IntegerField(_sbat_block_count_offset, _data).get();
new IntegerField(0x34, 0, _data);
new IntegerField(0x38, 0x1000, _data);
- // Initialise the variables
+ // Initialize the variables
_bat_count = 0;
_sbat_count = 0;
_xbat_count = 0;
* @exception IOException on problems writing to the specified
* stream
*/
- void writeData(final OutputStream stream)
- throws IOException
- {
+ void writeData(final OutputStream stream) throws IOException {
// Update the counts and start positions
new IntegerField(_bat_count_offset, _bat_count, _data);
new IntegerField(_property_start_offset, _property_start, _data);
stream.write(0);
}
}
+
+ private static boolean cmp(byte[] magic, byte[] data) {
+ int i=0;
+ for (byte m : magic) {
+ byte d = data[i++];
+ if (!(d == m || (m == 0x70 && (d == 0x10 || d == 0x20 || d == 0x40)))) {
+ return false;
+ }
+ }
+ return true;
+ }
}