Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

Sttb.java 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hwpf.model;
  16. import java.util.Arrays;
  17. import org.apache.logging.log4j.LogManager;
  18. import org.apache.poi.util.Internal;
  19. import org.apache.poi.util.LittleEndian;
  20. import org.apache.poi.util.LittleEndianConsts;
  21. import org.apache.poi.util.StringUtil;
  22. /**
  23. * The STTB is a string table that is made up of a header that is followed by an
  24. * array of elements. The cData value specifies the number of elements that are
  25. * contained in the array.
  26. */
  27. @Internal
  28. public class Sttb
  29. {
  30. private int _cbExtra;
  31. private final int _cDataLength;
  32. private String[] _data;
  33. private byte[][] _extraData;
  34. private final boolean _fExtend = true;
  35. public Sttb( byte[] buffer, int startOffset )
  36. {
  37. this( 2, buffer, startOffset );
  38. }
  39. public Sttb( int cDataLength, byte[] buffer, int startOffset )
  40. {
  41. this._cDataLength = cDataLength;
  42. fillFields( buffer, startOffset );
  43. }
  44. public Sttb( int cDataLength, String[] data )
  45. {
  46. this._cDataLength = cDataLength;
  47. this._data = Arrays.copyOf(data, data.length);
  48. this._cbExtra = 0;
  49. this._extraData = null;
  50. }
  51. public void fillFields( byte[] buffer, int startOffset )
  52. {
  53. short ffff = LittleEndian.getShort( buffer, startOffset );
  54. int offset = startOffset + LittleEndianConsts.SHORT_SIZE;
  55. if ( ffff != (short) 0xffff )
  56. {
  57. LogManager.getLogger(Sttb.class).atWarn().log(
  58. "Non-extended character Pascal strings are not supported right now. " +
  59. "Creating empty values in the RevisionMarkAuthorTable for now. " +
  60. "Please, contact POI developers for update."
  61. );
  62. //set data and extraData to empty values to avoid
  63. //downstream NPE in case someone calls getEntries on RevisionMarkAuthorTable
  64. _data = new String[0];
  65. _extraData = new byte[0][];
  66. return;
  67. }
  68. // strings are extended character strings
  69. int cData = _cDataLength == 2 ? LittleEndian.getUShort( buffer, offset )
  70. : LittleEndian.getInt( buffer, offset );
  71. offset += _cDataLength;
  72. this._cbExtra = LittleEndian.getUShort( buffer, offset );
  73. offset += 2;
  74. _data = new String[cData];
  75. _extraData = new byte[cData][];
  76. for ( int i = 0; i < cData; i++ )
  77. {
  78. int cchData = LittleEndian.getShort( buffer, offset );
  79. offset += 2;
  80. if ( cchData < 0 )
  81. continue;
  82. _data[i] = StringUtil.getFromUnicodeLE( buffer, offset, cchData );
  83. offset += cchData * 2;
  84. _extraData[i] = Arrays.copyOfRange( buffer, offset, offset+_cbExtra );
  85. offset += _cbExtra;
  86. }
  87. }
  88. /**
  89. * The definition of each STTB specifies the meaning of this field. If this
  90. * STTB uses extended characters, the size of this field is 2*cchData bytes
  91. * and it is a Unicode string unless otherwise specified by the STTB
  92. * definition. If this STTB does not use extended characters, then the size
  93. * of this field is cchData bytes and it is an ANSI string, unless otherwise
  94. * specified by the STTB definition.
  95. */
  96. public String[] getData()
  97. {
  98. return _data;
  99. }
  100. public int getSize()
  101. {
  102. // ffff
  103. int size = LittleEndianConsts.SHORT_SIZE;
  104. // cData
  105. size += _cDataLength;
  106. // cbExtra
  107. size += LittleEndianConsts.SHORT_SIZE;
  108. if ( this._fExtend )
  109. {
  110. for ( String data : _data )
  111. {
  112. // cchData
  113. size += LittleEndianConsts.SHORT_SIZE;
  114. // data
  115. size += 2 * (data == null ? 0 : data.length());
  116. }
  117. }
  118. else
  119. {
  120. for ( String data : _data )
  121. {
  122. // cchData
  123. size += LittleEndianConsts.BYTE_SIZE;
  124. // data
  125. size += (data == null ? 0 : data.length());
  126. }
  127. }
  128. // extraData
  129. if ( _extraData != null )
  130. {
  131. size += _cbExtra * _data.length;
  132. }
  133. return size;
  134. }
  135. public byte[] serialize()
  136. {
  137. final byte[] buffer = new byte[getSize()];
  138. LittleEndian.putShort( buffer, 0, (short) 0xffff );
  139. if ( _data == null || _data.length == 0 )
  140. {
  141. if ( _cDataLength == 4 )
  142. {
  143. LittleEndian.putInt( buffer, 2, 0 );
  144. LittleEndian.putUShort( buffer, 6, _cbExtra );
  145. return buffer;
  146. }
  147. LittleEndian.putUShort( buffer, 2, 0 );
  148. LittleEndian.putUShort( buffer, 4, _cbExtra );
  149. return buffer;
  150. }
  151. int offset;
  152. if ( _cDataLength == 4 )
  153. {
  154. LittleEndian.putInt( buffer, 2, _data.length );
  155. LittleEndian.putUShort( buffer, 6, _cbExtra );
  156. offset = 2 + LittleEndianConsts.INT_SIZE + LittleEndianConsts.SHORT_SIZE;
  157. }
  158. else
  159. {
  160. LittleEndian.putUShort( buffer, 2, _data.length );
  161. LittleEndian.putUShort( buffer, 4, _cbExtra );
  162. offset = 2 + LittleEndianConsts.SHORT_SIZE + LittleEndianConsts.SHORT_SIZE;
  163. }
  164. for ( int i = 0; i < _data.length; i++ )
  165. {
  166. String entry = _data[i];
  167. if ( entry == null )
  168. {
  169. // is it correct?
  170. buffer[offset] = -1;
  171. buffer[offset + 1] = 0;
  172. offset += 2;
  173. continue;
  174. }
  175. if ( _fExtend )
  176. {
  177. LittleEndian.putUShort( buffer, offset, entry.length() );
  178. offset += LittleEndianConsts.SHORT_SIZE;
  179. StringUtil.putUnicodeLE( entry, buffer, offset );
  180. offset += 2 * entry.length();
  181. }
  182. else
  183. {
  184. throw new UnsupportedOperationException(
  185. "ANSI STTB is not supported yet" );
  186. }
  187. if ( _cbExtra != 0 )
  188. {
  189. if ( _extraData[i] != null && _extraData[i].length != 0 )
  190. {
  191. System.arraycopy( _extraData[i], 0, buffer, offset,
  192. Math.min( _extraData[i].length, _cbExtra ) );
  193. }
  194. offset += _cbExtra;
  195. }
  196. }
  197. return buffer;
  198. }
  199. public int serialize( byte[] buffer, int offset )
  200. {
  201. byte[] bs = serialize();
  202. System.arraycopy( bs, 0, buffer, offset, bs.length );
  203. return bs.length;
  204. }
  205. }