Bug 56880 - switch exception to logged warning that non-extended pascal strings are not supported. Full fix would add parsing for these strings.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1728547 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tim Allison 2016-02-04 19:54:15 +00:00
parent d1e2c186ec
commit 991c5d0a00
1 changed files with 258 additions and 249 deletions

View File

@ -1,249 +1,258 @@
/* ==================================================================== /* ====================================================================
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
this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0 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 not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hwpf.model; package org.apache.poi.hwpf.model;
import org.apache.poi.util.LittleEndian; import java.util.Arrays;
import org.apache.poi.util.StringUtil;
import org.apache.poi.util.LittleEndian;
import java.util.Arrays; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
/** import org.apache.poi.util.StringUtil;
* The STTB is a string table that is made up of a header that is followed by an
* array of elements. The cData value specifies the number of elements that are /**
* contained in the array. * The STTB is a string table that is made up of a header that is followed by an
* <p> * array of elements. The cData value specifies the number of elements that are
* Class and fields descriptions are quoted from [MS-DOC] -- v20121003 Word * contained in the array.
* (.doc) Binary File Format; Copyright (c) 2012 Microsoft Corporation; Release: * <p>
* October 8, 2012 * Class and fields descriptions are quoted from [MS-DOC] -- v20121003 Word
* <p> * (.doc) Binary File Format; Copyright (c) 2012 Microsoft Corporation; Release:
* This class is internal. It content or properties may change without notice * October 8, 2012
* due to changes in our knowledge of internal Microsoft Word binary structures. * <p>
* * This class is internal. It content or properties may change without notice
* @author Sergey Vladimirov; according to [MS-DOC] -- v20121003 Word (.doc) * due to changes in our knowledge of internal Microsoft Word binary structures.
* Binary File Format; Copyright (c) 2012 Microsoft Corporation; *
* Release: October 8, 2012 * @author Sergey Vladimirov; according to [MS-DOC] -- v20121003 Word (.doc)
*/ * Binary File Format; Copyright (c) 2012 Microsoft Corporation;
public class Sttb * Release: October 8, 2012
{ */
public class Sttb
private int _cbExtra; {
private final int _cDataLength; private int _cbExtra;
private String[] _data; private final int _cDataLength;
private byte[][] _extraData; private String[] _data;
private final boolean _fExtend = true; private byte[][] _extraData;
public Sttb( byte[] buffer, int startOffset ) private final boolean _fExtend = true;
{
this( 2, buffer, startOffset ); public Sttb( byte[] buffer, int startOffset )
} {
this( 2, buffer, startOffset );
public Sttb( int cDataLength, byte[] buffer, int startOffset ) }
{
this._cDataLength = cDataLength; public Sttb( int cDataLength, byte[] buffer, int startOffset )
fillFields( buffer, startOffset ); {
} this._cDataLength = cDataLength;
fillFields( buffer, startOffset );
public Sttb( int cDataLength, String[] data ) }
{
this._cDataLength = cDataLength; public Sttb( int cDataLength, String[] data )
{
this._data = Arrays.copyOf(data, data.length); this._cDataLength = cDataLength;
this._cbExtra = 0; this._data = Arrays.copyOf(data, data.length);
this._extraData = null;
} this._cbExtra = 0;
this._extraData = null;
public void fillFields( byte[] buffer, int startOffset ) }
{
short ffff = LittleEndian.getShort( buffer, startOffset ); public void fillFields( byte[] buffer, int startOffset )
int offset = startOffset + LittleEndian.SHORT_SIZE; {
short ffff = LittleEndian.getShort( buffer, startOffset );
if ( ffff != (short) 0xffff ) int offset = startOffset + LittleEndian.SHORT_SIZE;
{
// Non-extended character Pascal strings if ( ffff != (short) 0xffff )
throw new UnsupportedOperationException( {
"Non-extended character Pascal strings are not supported right now. " POILogFactory.getLogger(Sttb.class).log(
+ "Please, contact POI developers for update." ); POILogger.WARN,
} "Non-extended character Pascal strings are not supported right now. "
// strings are extended character strings + "Creating empty values in the RevisionMarkAuthorTable for now. " +
"Please, contact POI developers for update.");
int cData = _cDataLength == 2 ? LittleEndian.getUShort( buffer, offset ) //set data and extraData to empty values to avoid
: LittleEndian.getInt( buffer, offset ); //downstream NPE in case someone calls getEntries on RevisionMarkAuthorTable
offset += _cDataLength; _data = new String[0];
_extraData = new byte[0][];
this._cbExtra = LittleEndian.getUShort( buffer, offset );
offset += 2; return;
}
_data = new String[cData]; // strings are extended character strings
_extraData = new byte[cData][];
int cData = _cDataLength == 2 ? LittleEndian.getUShort( buffer, offset )
for ( int i = 0; i < cData; i++ ) : LittleEndian.getInt( buffer, offset );
{ offset += _cDataLength;
int cchData = LittleEndian.getShort( buffer, offset );
offset += 2; this._cbExtra = LittleEndian.getUShort( buffer, offset );
offset += 2;
if ( cchData < 0 )
continue; _data = new String[cData];
_extraData = new byte[cData][];
_data[i] = StringUtil.getFromUnicodeLE( buffer, offset, cchData );
offset += cchData * 2; for ( int i = 0; i < cData; i++ )
{
_extraData[i] = LittleEndian int cchData = LittleEndian.getShort( buffer, offset );
.getByteArray( buffer, offset, _cbExtra ); offset += 2;
offset += _cbExtra;
} if ( cchData < 0 )
} continue;
/** _data[i] = StringUtil.getFromUnicodeLE( buffer, offset, cchData );
* The definition of each STTB specifies the meaning of this field. If this offset += cchData * 2;
* STTB uses extended characters, the size of this field is 2*cchData bytes
* and it is a Unicode string unless otherwise specified by the STTB _extraData[i] = LittleEndian
* definition. If this STTB does not use extended characters, then the size .getByteArray( buffer, offset, _cbExtra );
* of this field is cchData bytes and it is an ANSI string, unless otherwise offset += _cbExtra;
* specified by the STTB definition. }
*/ }
public String[] getData()
{ /**
return _data; * The definition of each STTB specifies the meaning of this field. If this
} * STTB uses extended characters, the size of this field is 2*cchData bytes
* and it is a Unicode string unless otherwise specified by the STTB
public int getSize() * definition. If this STTB does not use extended characters, then the size
{ * of this field is cchData bytes and it is an ANSI string, unless otherwise
// ffff * specified by the STTB definition.
int size = LittleEndian.SHORT_SIZE; */
public String[] getData()
// cData {
size += _cDataLength; return _data;
}
// cbExtra
size += LittleEndian.SHORT_SIZE; public int getSize()
{
if ( this._fExtend ) // ffff
{ int size = LittleEndian.SHORT_SIZE;
for ( String data : _data )
{ // cData
// cchData size += _cDataLength;
size += LittleEndian.SHORT_SIZE;
// data // cbExtra
size += 2 * data.length(); size += LittleEndian.SHORT_SIZE;
}
} if ( this._fExtend )
else {
{ for ( String data : _data )
for ( String data : _data ) {
{ // cchData
// cchData size += LittleEndian.SHORT_SIZE;
size += LittleEndian.BYTE_SIZE; // data
// data size += 2 * data.length();
size += 1 * data.length(); }
} }
} else
{
// extraData for ( String data : _data )
if ( _extraData != null ) {
{ // cchData
size += _cbExtra * _data.length; size += LittleEndian.BYTE_SIZE;
} // data
size += 1 * data.length();
return size; }
} }
public byte[] serialize() // extraData
{ if ( _extraData != null )
final byte[] buffer = new byte[getSize()]; {
size += _cbExtra * _data.length;
LittleEndian.putShort( buffer, 0, (short) 0xffff ); }
if ( _data == null || _data.length == 0 ) return size;
{ }
if ( _cDataLength == 4 )
{ public byte[] serialize()
LittleEndian.putInt( buffer, 2, 0 ); {
LittleEndian.putUShort( buffer, 6, _cbExtra ); final byte[] buffer = new byte[getSize()];
return buffer;
} LittleEndian.putShort( buffer, 0, (short) 0xffff );
LittleEndian.putUShort( buffer, 2, 0 ); if ( _data == null || _data.length == 0 )
LittleEndian.putUShort( buffer, 4, _cbExtra ); {
return buffer; if ( _cDataLength == 4 )
} {
LittleEndian.putInt( buffer, 2, 0 );
int offset; LittleEndian.putUShort( buffer, 6, _cbExtra );
if ( _cDataLength == 4 ) return buffer;
{ }
LittleEndian.putInt( buffer, 2, _data.length );
LittleEndian.putUShort( buffer, 6, _cbExtra ); LittleEndian.putUShort( buffer, 2, 0 );
offset = 2 + LittleEndian.INT_SIZE + LittleEndian.SHORT_SIZE; LittleEndian.putUShort( buffer, 4, _cbExtra );
} return buffer;
else }
{
LittleEndian.putUShort( buffer, 2, _data.length ); int offset;
LittleEndian.putUShort( buffer, 4, _cbExtra ); if ( _cDataLength == 4 )
offset = 2 + LittleEndian.SHORT_SIZE + LittleEndian.SHORT_SIZE; {
} LittleEndian.putInt( buffer, 2, _data.length );
LittleEndian.putUShort( buffer, 6, _cbExtra );
for ( int i = 0; i < _data.length; i++ ) offset = 2 + LittleEndian.INT_SIZE + LittleEndian.SHORT_SIZE;
{ }
String entry = _data[i]; else
if ( entry == null ) {
{ LittleEndian.putUShort( buffer, 2, _data.length );
// is it correct? LittleEndian.putUShort( buffer, 4, _cbExtra );
buffer[offset] = -1; offset = 2 + LittleEndian.SHORT_SIZE + LittleEndian.SHORT_SIZE;
buffer[offset + 1] = 0; }
offset += 2;
continue; for ( int i = 0; i < _data.length; i++ )
} {
String entry = _data[i];
if ( _fExtend ) if ( entry == null )
{ {
LittleEndian.putUShort( buffer, offset, entry.length() ); // is it correct?
offset += LittleEndian.SHORT_SIZE; buffer[offset] = -1;
buffer[offset + 1] = 0;
StringUtil.putUnicodeLE( entry, buffer, offset ); offset += 2;
offset += 2 * entry.length(); continue;
} }
else
{ if ( _fExtend )
throw new UnsupportedOperationException( {
"ANSI STTB is not supported yet" ); LittleEndian.putUShort( buffer, offset, entry.length() );
} offset += LittleEndian.SHORT_SIZE;
if ( _cbExtra != 0 ) StringUtil.putUnicodeLE( entry, buffer, offset );
{ offset += 2 * entry.length();
if ( _extraData[i] != null && _extraData[i].length != 0 ) }
{ else
System.arraycopy( _extraData[i], 0, buffer, offset, {
Math.min( _extraData[i].length, _cbExtra ) ); throw new UnsupportedOperationException(
} "ANSI STTB is not supported yet" );
offset += _cbExtra; }
}
} if ( _cbExtra != 0 )
{
return buffer; if ( _extraData[i] != null && _extraData[i].length != 0 )
} {
System.arraycopy( _extraData[i], 0, buffer, offset,
public int serialize( byte[] buffer, int offset ) Math.min( _extraData[i].length, _cbExtra ) );
{ }
byte[] bs = serialize(); offset += _cbExtra;
System.arraycopy( bs, 0, buffer, offset, bs.length ); }
return bs.length; }
}
} return buffer;
}
public int serialize( byte[] buffer, int offset )
{
byte[] bs = serialize();
System.arraycopy( bs, 0, buffer, offset, bs.length );
return bs.length;
}
}