Bugzilla 47479 - Fix BoolErrRecord to tolerate incorrect format written by OOO
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@791595 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
15ffa9ebda
commit
9ba354156d
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.5-beta7" date="2009-??-??">
|
<release version="3.5-beta7" date="2009-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">47479 - Fix BoolErrRecord to tolerate incorrect format written by OOO</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">47448 - Allow HSSFEventFactory to handle non-zero padding at the end of the workbook stream</action>
|
<action dev="POI-DEVELOPERS" type="fix">47448 - Allow HSSFEventFactory to handle non-zero padding at the end of the workbook stream</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">47456 - Support for getting OLE object data in PowerPointExtractor</action>
|
<action dev="POI-DEVELOPERS" type="add">47456 - Support for getting OLE object data in PowerPointExtractor</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">47411 - Explicitly set the 1900 date system when creating XSSF workbooks</action>
|
<action dev="POI-DEVELOPERS" type="fix">47411 - Explicitly set the 1900 date system when creating XSSF workbooks</action>
|
||||||
|
@ -29,8 +29,11 @@ import org.apache.poi.util.LittleEndianOutput;
|
|||||||
*/
|
*/
|
||||||
public final class BoolErrRecord extends CellRecord {
|
public final class BoolErrRecord extends CellRecord {
|
||||||
public final static short sid = 0x0205;
|
public final static short sid = 0x0205;
|
||||||
private byte field_4_bBoolErr;
|
private int _value;
|
||||||
private byte field_5_fError;
|
/**
|
||||||
|
* If <code>true</code>, this record represents an error cell value, otherwise this record represents a boolean cell value
|
||||||
|
*/
|
||||||
|
private boolean _isError;
|
||||||
|
|
||||||
/** Creates new BoolErrRecord */
|
/** Creates new BoolErrRecord */
|
||||||
public BoolErrRecord() {
|
public BoolErrRecord() {
|
||||||
@ -42,8 +45,29 @@ public final class BoolErrRecord extends CellRecord {
|
|||||||
*/
|
*/
|
||||||
public BoolErrRecord(RecordInputStream in) {
|
public BoolErrRecord(RecordInputStream in) {
|
||||||
super(in);
|
super(in);
|
||||||
field_4_bBoolErr = in.readByte();
|
switch (in.remaining()) {
|
||||||
field_5_fError = in.readByte();
|
case 2:
|
||||||
|
_value = in.readByte();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
_value = in.readUShort();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RecordFormatException("Unexpected size ("
|
||||||
|
+ in.remaining() + ") for BOOLERR record.");
|
||||||
|
}
|
||||||
|
int flag = in.readUByte();
|
||||||
|
switch (flag) {
|
||||||
|
case 0:
|
||||||
|
_isError = false;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
_isError = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RecordFormatException("Unexpected isError flag ("
|
||||||
|
+ flag + ") for BOOLERR record.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,8 +76,8 @@ public final class BoolErrRecord extends CellRecord {
|
|||||||
* @param value representing the boolean value
|
* @param value representing the boolean value
|
||||||
*/
|
*/
|
||||||
public void setValue(boolean value) {
|
public void setValue(boolean value) {
|
||||||
field_4_bBoolErr = value ? ( byte ) 1 : ( byte ) 0;
|
_value = value ? 1 : 0;
|
||||||
field_5_fError = ( byte ) 0;
|
_isError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,8 +96,8 @@ public final class BoolErrRecord extends CellRecord {
|
|||||||
case ErrorConstants.ERROR_NAME:
|
case ErrorConstants.ERROR_NAME:
|
||||||
case ErrorConstants.ERROR_NUM:
|
case ErrorConstants.ERROR_NUM:
|
||||||
case ErrorConstants.ERROR_NA:
|
case ErrorConstants.ERROR_NA:
|
||||||
field_4_bBoolErr = value;
|
_value = value;
|
||||||
field_5_fError = ( byte ) 1;
|
_isError = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Error Value can only be 0,7,15,23,29,36 or 42. It cannot be "+value);
|
throw new IllegalArgumentException("Error Value can only be 0,7,15,23,29,36 or 42. It cannot be "+value);
|
||||||
@ -85,7 +109,7 @@ public final class BoolErrRecord extends CellRecord {
|
|||||||
* @return boolean representing the boolean value
|
* @return boolean representing the boolean value
|
||||||
*/
|
*/
|
||||||
public boolean getBooleanValue() {
|
public boolean getBooleanValue() {
|
||||||
return (field_4_bBoolErr != 0);
|
return _value != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,7 +118,7 @@ public final class BoolErrRecord extends CellRecord {
|
|||||||
* @return byte representing the error value
|
* @return byte representing the error value
|
||||||
*/
|
*/
|
||||||
public byte getErrorValue() {
|
public byte getErrorValue() {
|
||||||
return field_4_bBoolErr;
|
return (byte)_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,14 +127,7 @@ public final class BoolErrRecord extends CellRecord {
|
|||||||
* @return boolean true if the cell holds a boolean value
|
* @return boolean true if the cell holds a boolean value
|
||||||
*/
|
*/
|
||||||
public boolean isBoolean() {
|
public boolean isBoolean() {
|
||||||
return (field_5_fError == ( byte ) 0);
|
return !_isError;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* manually indicate this is an error rather than a boolean
|
|
||||||
*/
|
|
||||||
public void setError(boolean val) {
|
|
||||||
field_5_fError = (byte) (val == false ? 0 : 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,9 +135,8 @@ public final class BoolErrRecord extends CellRecord {
|
|||||||
*
|
*
|
||||||
* @return boolean true if the cell holds an error value
|
* @return boolean true if the cell holds an error value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public boolean isError() {
|
public boolean isError() {
|
||||||
return field_5_fError != 0;
|
return _isError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -140,8 +156,8 @@ public final class BoolErrRecord extends CellRecord {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void serializeValue(LittleEndianOutput out) {
|
protected void serializeValue(LittleEndianOutput out) {
|
||||||
out.writeByte(field_4_bBoolErr);
|
out.writeByte(_value);
|
||||||
out.writeByte(field_5_fError);
|
out.writeByte(_isError ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -156,8 +172,8 @@ public final class BoolErrRecord extends CellRecord {
|
|||||||
public Object clone() {
|
public Object clone() {
|
||||||
BoolErrRecord rec = new BoolErrRecord();
|
BoolErrRecord rec = new BoolErrRecord();
|
||||||
copyBaseFields(rec);
|
copyBaseFields(rec);
|
||||||
rec.field_4_bBoolErr = field_4_bBoolErr;
|
rec._value = _value;
|
||||||
rec.field_5_fError = field_5_fError;
|
rec._isError = _isError;
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ public final class AllRecordTests {
|
|||||||
result.addTest(AllRecordAggregateTests.suite());
|
result.addTest(AllRecordAggregateTests.suite());
|
||||||
|
|
||||||
result.addTestSuite(TestBOFRecord.class);
|
result.addTestSuite(TestBOFRecord.class);
|
||||||
|
result.addTestSuite(TestBoolErrRecord.class);
|
||||||
result.addTestSuite(TestBoundSheetRecord.class);
|
result.addTestSuite(TestBoundSheetRecord.class);
|
||||||
result.addTestSuite(TestCFHeaderRecord.class);
|
result.addTestSuite(TestCFHeaderRecord.class);
|
||||||
result.addTestSuite(TestCFRuleRecord.class);
|
result.addTestSuite(TestCFRuleRecord.class);
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.hssf.record;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import junit.framework.AssertionFailedError;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.RecordInputStream.LeftoverDataException;
|
||||||
|
import org.apache.poi.util.HexRead;
|
||||||
|
/**
|
||||||
|
* Tests for {@link BoolErrRecord}
|
||||||
|
*/
|
||||||
|
public final class TestBoolErrRecord extends TestCase {
|
||||||
|
|
||||||
|
public void testError() {
|
||||||
|
byte[] data = HexRead.readFromString(
|
||||||
|
"00 00 00 00 0F 00 " + // row, col, xfIndex
|
||||||
|
"07 01 " // #DIV/0!, isError
|
||||||
|
);
|
||||||
|
|
||||||
|
RecordInputStream in = TestcaseRecordInputStream.create(BoolErrRecord.sid, data);
|
||||||
|
BoolErrRecord ber = new BoolErrRecord(in);
|
||||||
|
assertTrue(ber.isError());
|
||||||
|
assertEquals(7, ber.getErrorValue());
|
||||||
|
|
||||||
|
TestcaseRecordInputStream.confirmRecordEncoding(BoolErrRecord.sid, data, ber.serialize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bugzilla 47479 was due to an apparent error in OOO which (as of version 3.0.1)
|
||||||
|
* writes the <i>value</i> field of BOOLERR records as 2 bytes instead of 1.<br/>
|
||||||
|
* Coincidentally, the extra byte written is zero, which is exactly the value
|
||||||
|
* required by the <i>isError</i> field. This probably why Excel seems to have
|
||||||
|
* no problem. OOO does not have the same bug for error values (which wouldn't
|
||||||
|
* work by the same coincidence).
|
||||||
|
*/
|
||||||
|
public void testOooBadFormat_bug47479() {
|
||||||
|
byte[] data = HexRead.readFromString(
|
||||||
|
"05 02 09 00 " + // sid, size
|
||||||
|
"00 00 00 00 0F 00 " + // row, col, xfIndex
|
||||||
|
"01 00 00 " // extra 00 byte here
|
||||||
|
);
|
||||||
|
|
||||||
|
RecordInputStream in = TestcaseRecordInputStream.create(data);
|
||||||
|
BoolErrRecord ber = new BoolErrRecord(in);
|
||||||
|
boolean hasMore;
|
||||||
|
try {
|
||||||
|
hasMore = in.hasNextRecord();
|
||||||
|
} catch (LeftoverDataException e) {
|
||||||
|
if ("Initialisation of record 0x205 left 1 bytes remaining still to be read.".equals(e.getMessage())) {
|
||||||
|
throw new AssertionFailedError("Identified bug 47479");
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
assertFalse(hasMore);
|
||||||
|
assertTrue(ber.isBoolean());
|
||||||
|
assertEquals(true, ber.getBooleanValue());
|
||||||
|
|
||||||
|
// Check that the record re-serializes correctly
|
||||||
|
byte[] outData = ber.serialize();
|
||||||
|
byte[] expData = HexRead.readFromString(
|
||||||
|
"05 02 08 00 " +
|
||||||
|
"00 00 00 00 0F 00 " +
|
||||||
|
"01 00 " // normal number of data bytes
|
||||||
|
);
|
||||||
|
assertTrue(Arrays.equals(expData, outData));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user