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