fix field updating in AbstractEscherOptRecord;

prevent from shooting into foot by updating AbstractEscherOptRecord with incorrect values

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1165603 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sergey Vladimirov 2011-09-06 11:13:41 +00:00
parent 41e3bd5214
commit 3e6b5ac3ff
4 changed files with 76 additions and 86 deletions

View File

@ -47,10 +47,11 @@ public abstract class AbstractEscherOptRecord extends EscherRecord
EscherRecordFactory recordFactory )
{
int bytesRemaining = readHeader( data, offset );
short propertiesCount = readInstance( data, offset );
int pos = offset + 8;
EscherPropertyFactory f = new EscherPropertyFactory();
properties = f.createProperties( data, pos, getInstance() );
properties = f.createProperties( data, pos, propertiesCount );
return bytesRemaining + 8;
}

View File

@ -21,6 +21,8 @@ import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.util.LittleEndian;
/**
* Generates escher records when provided the byte array containing those records.
*
@ -55,43 +57,45 @@ public class DefaultEscherRecordFactory implements EscherRecordFactory {
* @return The generated escher record
*/
public EscherRecord createRecord(byte[] data, int offset) {
EscherRecord.EscherRecordHeader header = EscherRecord.EscherRecordHeader.readHeader( data, offset );
short options = LittleEndian.getShort( data, offset );
short recordId = LittleEndian.getShort( data, offset + 2 );
// int remainingBytes = LittleEndian.getInt( data, offset + 4 );
// Options of 0x000F means container record
// However, EscherTextboxRecord are containers of records for the
// host application, not of other Escher records, so treat them
// differently
if ( ( header.getOptions() & (short) 0x000F ) == (short) 0x000F
&& header.getRecordId() != EscherTextboxRecord.RECORD_ID ) {
if ( ( options & (short) 0x000F ) == (short) 0x000F
&& recordId != EscherTextboxRecord.RECORD_ID ) {
EscherContainerRecord r = new EscherContainerRecord();
r.setRecordId( header.getRecordId() );
r.setOptions( header.getOptions() );
r.setRecordId( recordId );
r.setOptions( options );
return r;
}
if (header.getRecordId() >= EscherBlipRecord.RECORD_ID_START
&& header.getRecordId() <= EscherBlipRecord.RECORD_ID_END) {
if (recordId >= EscherBlipRecord.RECORD_ID_START
&& recordId <= EscherBlipRecord.RECORD_ID_END) {
EscherBlipRecord r;
if (header.getRecordId() == EscherBitmapBlip.RECORD_ID_DIB ||
header.getRecordId() == EscherBitmapBlip.RECORD_ID_JPEG ||
header.getRecordId() == EscherBitmapBlip.RECORD_ID_PNG)
if (recordId == EscherBitmapBlip.RECORD_ID_DIB ||
recordId == EscherBitmapBlip.RECORD_ID_JPEG ||
recordId == EscherBitmapBlip.RECORD_ID_PNG)
{
r = new EscherBitmapBlip();
}
else if (header.getRecordId() == EscherMetafileBlip.RECORD_ID_EMF ||
header.getRecordId() == EscherMetafileBlip.RECORD_ID_WMF ||
header.getRecordId() == EscherMetafileBlip.RECORD_ID_PICT)
else if (recordId == EscherMetafileBlip.RECORD_ID_EMF ||
recordId == EscherMetafileBlip.RECORD_ID_WMF ||
recordId == EscherMetafileBlip.RECORD_ID_PICT)
{
r = new EscherMetafileBlip();
} else {
r = new EscherBlipRecord();
}
r.setRecordId( header.getRecordId() );
r.setOptions( header.getOptions() );
r.setRecordId( recordId );
r.setOptions( options );
return r;
}
Constructor<? extends EscherRecord> recordConstructor = recordsMap.get(Short.valueOf(header.getRecordId()));
Constructor<? extends EscherRecord> recordConstructor = recordsMap.get(Short.valueOf(recordId));
EscherRecord escherRecord = null;
if (recordConstructor == null) {
return new UnknownEscherRecord();
@ -101,8 +105,8 @@ public class DefaultEscherRecordFactory implements EscherRecordFactory {
} catch (Exception e) {
return new UnknownEscherRecord();
}
escherRecord.setRecordId(header.getRecordId());
escherRecord.setOptions(header.getOptions());
escherRecord.setRecordId(recordId);
escherRecord.setOptions(options);
return escherRecord;
}

View File

@ -26,15 +26,25 @@ package org.apache.poi.ddf;
*/
public class EscherOptRecord extends AbstractEscherOptRecord
{
public static final short RECORD_ID = (short) 0xF00B;
public static final String RECORD_DESCRIPTION = "msofbtOPT";
public static final short RECORD_ID = (short) 0xF00B;
@Override
public short getInstance()
{
setInstance( (short) properties.size() );
return super.getInstance();
}
/**
* Automatically recalculate the correct option
*/
@Deprecated
public short getOptions()
{
setOptions( (short) ( ( properties.size() << 4 ) | 0x3 ) );
// update values
getInstance();
getVersion();
return super.getOptions();
}
@ -42,4 +52,21 @@ public class EscherOptRecord extends AbstractEscherOptRecord
{
return "Opt";
}
@Override
public short getVersion()
{
setVersion( (short) 0x3 );
return super.getVersion();
}
@Override
public void setVersion( short value )
{
if ( value != 0x3 )
throw new IllegalArgumentException( RECORD_DESCRIPTION
+ " can have only '0x3' version" );
super.setVersion( value );
}
}

View File

@ -77,11 +77,24 @@ public abstract class EscherRecord {
* @return the number of bytes remaining in this record. This
* may include the children if this is a container.
*/
protected int readHeader( byte[] data, int offset ) {
EscherRecordHeader header = EscherRecordHeader.readHeader(data, offset);
_options = header.getOptions();
_recordId = header.getRecordId();
return header.getRemainingBytes();
protected int readHeader( byte[] data, int offset )
{
_options = LittleEndian.getShort( data, offset );
_recordId = LittleEndian.getShort( data, offset + 2 );
int remainingBytes = LittleEndian.getInt( data, offset + 4 );
return remainingBytes;
}
/**
* Read the options field from header and return instance part of it.
* @param data the byte array to read from
* @param offset the offset to start reading from
* @return value of instance part of options field
*/
protected static short readInstance( byte data[], int offset )
{
final short options = LittleEndian.getShort( data, offset );
return fInstance.getShortValue( options );
}
/**
@ -112,6 +125,9 @@ public abstract class EscherRecord {
*/
@Deprecated
public void setOptions( short options ) {
// call to handle correct/incorrect values
setVersion( fVersion.getShortValue( options ) );
setInstance( fInstance.getShortValue( options ) );
_options = options;
}
@ -252,7 +268,7 @@ public abstract class EscherRecord {
*/
public void setInstance( short value )
{
fInstance.setShortValue( _options, value );
_options = fInstance.setShortValue( _options, value );
}
/**
@ -273,64 +289,6 @@ public abstract class EscherRecord {
*/
public void setVersion( short value )
{
fVersion.setShortValue( _options, value );
}
/**
* This class reads the standard escher header.
*/
static class EscherRecordHeader
{
private short options;
private short recordId;
private int remainingBytes;
private EscherRecordHeader() {
// fields uninitialised
}
public static EscherRecordHeader readHeader( byte[] data, int offset )
{
EscherRecordHeader header = new EscherRecordHeader();
header.options = LittleEndian.getShort(data, offset);
header.recordId = LittleEndian.getShort(data, offset + 2);
header.remainingBytes = LittleEndian.getInt( data, offset + 4 );
return header;
}
public byte getVersion()
{
return (byte) fVersion.getShortValue( options );
}
public short getInstance()
{
return fInstance.getShortValue( options );
}
public short getOptions()
{
return options;
}
public short getRecordId()
{
return recordId;
}
public int getRemainingBytes()
{
return remainingBytes;
}
public String toString()
{
return "EscherRecordHeader{" +
"ver=" + getVersion() +
"instance=" + getInstance() +
", recordId=" + recordId +
", remainingBytes=" + remainingBytes +
"}";
}
_options = fVersion.setShortValue( _options, value );
}
}