You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FileInformationBlock.java 34KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  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.io.ByteArrayOutputStream;
  17. import java.io.IOException;
  18. import java.lang.reflect.Method;
  19. import java.lang.reflect.Modifier;
  20. import java.util.HashSet;
  21. import java.util.Locale;
  22. import org.apache.poi.hwpf.model.types.FibBaseAbstractType;
  23. import org.apache.poi.hwpf.model.types.FibRgW97AbstractType;
  24. import org.apache.poi.util.IOUtils;
  25. import org.apache.poi.util.Internal;
  26. import org.apache.poi.util.LittleEndian;
  27. import org.apache.poi.util.LittleEndianConsts;
  28. import org.apache.poi.util.POILogFactory;
  29. import org.apache.poi.util.POILogger;
  30. /**
  31. * <p>The File Information Block (FIB). Holds pointers
  32. * to various bits of the file, and lots of flags which
  33. * specify properties of the document.<p>
  34. * <ul>
  35. * <li>The {@link FibBase} class, holds the first 32 bytes.</li>
  36. * <li>The next part, the fibRgW / FibRgW97, is handled by the {@link FibRgW97}.</li>
  37. * <li>The next part, the fibRgLw / FibRgLw97, is handled by the {@link FibRgLw97}.</li>
  38. * <li>Finally, the rest of the fields are handled by the {@link FIBFieldHandler}.</li>
  39. * </ul>
  40. */
  41. @Internal
  42. public final class FileInformationBlock
  43. {
  44. //arbitrarily selected; may need to increase
  45. private static final int MAX_RECORD_LENGTH = 100_000;
  46. public static final POILogger logger = POILogFactory
  47. .getLogger( FileInformationBlock.class );
  48. private FibBase _fibBase;
  49. private int _csw;
  50. private FibRgW97 _fibRgW;
  51. private int _cslw;
  52. private FibRgLw _fibRgLw;
  53. private int _cbRgFcLcb;
  54. private FIBFieldHandler _fieldHandler;
  55. private int _cswNew;
  56. private int _nFibNew;
  57. private byte[] _fibRgCswNew;
  58. /** Creates a new instance of FileInformationBlock */
  59. public FileInformationBlock( byte[] mainDocument )
  60. {
  61. int offset = 0;
  62. _fibBase = new FibBase( mainDocument, offset );
  63. offset = FibBaseAbstractType.getSize();
  64. assert offset == 32;
  65. _csw = LittleEndian.getUShort( mainDocument, offset );
  66. offset += LittleEndianConsts.SHORT_SIZE;
  67. _fibRgW = new FibRgW97( mainDocument, offset );
  68. offset += FibRgW97AbstractType.getSize();
  69. assert offset == 62;
  70. _cslw = LittleEndian.getUShort( mainDocument, offset );
  71. offset += LittleEndianConsts.SHORT_SIZE;
  72. if ( _fibBase.getNFib() < 105 )
  73. {
  74. _fibRgLw = new FibRgLw95( mainDocument, offset );
  75. offset += FibRgLw97.getSize();
  76. // magic number, run tests after changes
  77. _cbRgFcLcb = 74;
  78. // skip fibRgFcLcbBlob (read later at fillVariableFields)
  79. offset += _cbRgFcLcb * LittleEndianConsts.INT_SIZE * 2;
  80. _cswNew = LittleEndian.getUShort( mainDocument, offset );
  81. offset += LittleEndianConsts.SHORT_SIZE;
  82. _cswNew = 0;
  83. _nFibNew = -1;
  84. _fibRgCswNew = new byte[0];
  85. return;
  86. }
  87. _fibRgLw = new FibRgLw97( mainDocument, offset );
  88. offset += FibRgLw97.getSize();
  89. assert offset == 152;
  90. _cbRgFcLcb = LittleEndian.getUShort( mainDocument, offset );
  91. offset += LittleEndianConsts.SHORT_SIZE;
  92. assert offset == 154;
  93. // skip fibRgFcLcbBlob (read later at fillVariableFields)
  94. offset += _cbRgFcLcb * LittleEndianConsts.INT_SIZE * 2;
  95. _cswNew = LittleEndian.getUShort( mainDocument, offset );
  96. offset += LittleEndianConsts.SHORT_SIZE;
  97. if ( _cswNew != 0 )
  98. {
  99. _nFibNew = LittleEndian.getUShort( mainDocument, offset );
  100. offset += LittleEndianConsts.SHORT_SIZE;
  101. // first short is already read as _nFibNew
  102. final int fibRgCswNewLength = ( _cswNew - 1 )
  103. * LittleEndianConsts.SHORT_SIZE;
  104. _fibRgCswNew = IOUtils.safelyAllocate(fibRgCswNewLength, MAX_RECORD_LENGTH);
  105. LittleEndian.getByteArray( mainDocument, offset, fibRgCswNewLength, MAX_RECORD_LENGTH );
  106. offset += fibRgCswNewLength;
  107. }
  108. else
  109. {
  110. _nFibNew = -1;
  111. _fibRgCswNew = new byte[0];
  112. }
  113. assertCbRgFcLcb();
  114. assertCswNew();
  115. }
  116. private void assertCbRgFcLcb()
  117. {
  118. int nfib = getNFib();
  119. String nfibHex = String.format(Locale.ROOT, "%04X", nfib);
  120. // Note - CommonCrawl shows there's more variation in these than
  121. // the documentation suggests, so accept common clusters around
  122. // the "correct" value as well
  123. switch ( nfib )
  124. {
  125. case 0x0071:
  126. // Found in CommonCrawl corpus but not in the docs...
  127. break;
  128. case 0x00BE:
  129. case 0x00BF:
  130. case 0x00C0:
  131. case 0x00C1: // Docs "official"
  132. case 0x00C2:
  133. case 0x00C3:
  134. assertCbRgFcLcb(nfibHex, 0x005D, "0x005D", _cbRgFcLcb );
  135. break;
  136. case 0x00D8:
  137. case 0x00D9: // Docs "official"
  138. assertCbRgFcLcb(nfibHex, 0x006C, "0x006C", _cbRgFcLcb );
  139. break;
  140. case 0x0101:
  141. assertCbRgFcLcb( "0x0101", 0x0088, "0x0088", _cbRgFcLcb );
  142. break;
  143. // TODO Is CommonCrawl 265 = 0x109 the one above or below?
  144. case 0x010B:
  145. case 0x010C: // Docs "official"
  146. assertCbRgFcLcb(nfibHex, 0x00A4, "0x00A4", _cbRgFcLcb );
  147. break;
  148. case 0x0112:
  149. assertCbRgFcLcb( "0x0112", 0x00B7, "0x00B7", _cbRgFcLcb );
  150. break;
  151. default:
  152. /* The Word spec has a much smaller list of "valid" values
  153. * to what the large CommonCrawl corpus contains!
  154. */
  155. logger.log(POILogger.WARN, "Invalid file format version number: " + nfib + "("+nfibHex+")");
  156. }
  157. }
  158. private static void assertCbRgFcLcb( final String strNFib,
  159. final int expectedCbRgFcLcb, final String strCbRgFcLcb,
  160. final int cbRgFcLcb )
  161. {
  162. if ( cbRgFcLcb == expectedCbRgFcLcb )
  163. return;
  164. logger.log( POILogger.WARN, "Since FIB.nFib == ", strNFib,
  165. " value of FIB.cbRgFcLcb MUST be ", strCbRgFcLcb + ", not 0x",
  166. Integer.toHexString( cbRgFcLcb ) );
  167. }
  168. private void assertCswNew()
  169. {
  170. switch ( getNFib() )
  171. {
  172. case 0x00C1:
  173. assertCswNew( "0x00C1", 0x0000, "0x0000", _cswNew );
  174. break;
  175. case 0x00D9:
  176. assertCswNew( "0x00D9", 0x0002, "0x0002", _cswNew );
  177. break;
  178. case 0x0101:
  179. assertCswNew( "0x0101", 0x0002, "0x0002", _cswNew );
  180. break;
  181. case 0x010C:
  182. assertCswNew( "0x010C", 0x0002, "0x0002", _cswNew );
  183. break;
  184. case 0x0112:
  185. assertCswNew( "0x0112", 0x0005, "0x0005", _cswNew );
  186. break;
  187. default:
  188. logger.log(POILogger.WARN, "Invalid file format version number: " + getNFib());
  189. }
  190. }
  191. private static void assertCswNew( final String strNFib,
  192. final int expectedCswNew, final String strExpectedCswNew,
  193. final int cswNew )
  194. {
  195. if ( cswNew == expectedCswNew )
  196. return;
  197. logger.log( POILogger.WARN, "Since FIB.nFib == ", strNFib,
  198. " value of FIB.cswNew MUST be ",
  199. strExpectedCswNew + ", not 0x", Integer.toHexString( cswNew ) );
  200. }
  201. public void fillVariableFields( byte[] mainDocument, byte[] tableStream )
  202. {
  203. /*
  204. * Listed fields won't be treat as UnhandledDataStructure. For all other
  205. * fields FIBFieldHandler will load it content into
  206. * UnhandledDataStructure and save them on save.
  207. */
  208. HashSet<Integer> knownFieldSet = new HashSet<>();
  209. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STSHF ) );
  210. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.CLX ) );
  211. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.DOP ) );
  212. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBTECHPX ) );
  213. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBTEPAPX ) );
  214. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFSED ) );
  215. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLFLST ) );
  216. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLFLFO ) );
  217. // field info
  218. for ( FieldsDocumentPart part : FieldsDocumentPart.values() )
  219. knownFieldSet.add( Integer.valueOf( part.getFibFieldsField() ) );
  220. // bookmarks
  221. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBKF ) );
  222. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBKL ) );
  223. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBFBKMK ) );
  224. // notes
  225. for ( NoteType noteType : NoteType.values() )
  226. {
  227. knownFieldSet.add( Integer.valueOf( noteType
  228. .getFibDescriptorsFieldIndex() ) );
  229. knownFieldSet.add( Integer.valueOf( noteType
  230. .getFibTextPositionsFieldIndex() ) );
  231. }
  232. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBFFFN ) );
  233. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBFRMARK ) );
  234. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBSAVEDBY ) );
  235. knownFieldSet.add( Integer.valueOf( FIBFieldHandler.MODIFIED ) );
  236. _fieldHandler = new FIBFieldHandler( mainDocument, 154, _cbRgFcLcb,
  237. tableStream, knownFieldSet, true );
  238. }
  239. @Override
  240. public String toString()
  241. {
  242. StringBuilder stringBuilder = new StringBuilder( );
  243. stringBuilder.append( _fibBase );
  244. stringBuilder.append( "[FIB2]\n" );
  245. stringBuilder.append( "\tSubdocuments info:\n" );
  246. for ( SubdocumentType type : SubdocumentType.values() )
  247. {
  248. stringBuilder.append( "\t\t" );
  249. stringBuilder.append( type );
  250. stringBuilder.append( " has length of " );
  251. stringBuilder.append( getSubdocumentTextStreamLength( type ) );
  252. stringBuilder.append( " char(s)\n" );
  253. }
  254. stringBuilder.append( "\tFields PLCF info:\n" );
  255. for ( FieldsDocumentPart part : FieldsDocumentPart.values() )
  256. {
  257. stringBuilder.append( "\t\t" );
  258. stringBuilder.append( part );
  259. stringBuilder.append( ": PLCF starts at " );
  260. stringBuilder.append( getFieldsPlcfOffset( part ) );
  261. stringBuilder.append( " and have length of " );
  262. stringBuilder.append( getFieldsPlcfLength( part ) );
  263. stringBuilder.append( "\n" );
  264. }
  265. stringBuilder.append( "\tNotes PLCF info:\n" );
  266. for ( NoteType noteType : NoteType.values() )
  267. {
  268. stringBuilder.append( "\t\t" );
  269. stringBuilder.append( noteType );
  270. stringBuilder.append( ": descriptions starts " );
  271. stringBuilder.append( getNotesDescriptorsOffset( noteType ) );
  272. stringBuilder.append( " and have length of " );
  273. stringBuilder.append( getNotesDescriptorsSize( noteType ) );
  274. stringBuilder.append( " bytes\n" );
  275. stringBuilder.append( "\t\t" );
  276. stringBuilder.append( noteType );
  277. stringBuilder.append( ": text positions starts " );
  278. stringBuilder.append( getNotesTextPositionsOffset( noteType ) );
  279. stringBuilder.append( " and have length of " );
  280. stringBuilder.append( getNotesTextPositionsSize( noteType ) );
  281. stringBuilder.append( " bytes\n" );
  282. }
  283. stringBuilder.append( _fieldHandler );
  284. try
  285. {
  286. stringBuilder.append( "\tJava reflection info:\n" );
  287. for ( Method method : FileInformationBlock.class.getMethods() )
  288. {
  289. if ( !method.getName().startsWith( "get" )
  290. || !Modifier.isPublic( method.getModifiers() )
  291. || Modifier.isStatic( method.getModifiers() )
  292. || method.getParameterTypes().length > 0 )
  293. continue;
  294. stringBuilder.append( "\t\t" );
  295. stringBuilder.append( method.getName() );
  296. stringBuilder.append( " => " );
  297. stringBuilder.append( method.invoke( this ) );
  298. stringBuilder.append( "\n" );
  299. }
  300. }
  301. catch ( Exception exc )
  302. {
  303. stringBuilder.append("(exc: ").append(exc.getMessage()).append(")");
  304. }
  305. stringBuilder.append( "[/FIB2]\n" );
  306. return stringBuilder.toString();
  307. }
  308. public int getNFib()
  309. {
  310. if ( _cswNew == 0 )
  311. return _fibBase.getNFib();
  312. return _nFibNew;
  313. }
  314. public int getFcDop()
  315. {
  316. return _fieldHandler.getFieldOffset(FIBFieldHandler.DOP);
  317. }
  318. public void setFcDop(int fcDop)
  319. {
  320. _fieldHandler.setFieldOffset(FIBFieldHandler.DOP, fcDop);
  321. }
  322. public int getLcbDop()
  323. {
  324. return _fieldHandler.getFieldSize(FIBFieldHandler.DOP);
  325. }
  326. public void setLcbDop(int lcbDop)
  327. {
  328. _fieldHandler.setFieldSize(FIBFieldHandler.DOP, lcbDop);
  329. }
  330. public int getFcStshf()
  331. {
  332. return _fieldHandler.getFieldOffset(FIBFieldHandler.STSHF);
  333. }
  334. public int getLcbStshf()
  335. {
  336. return _fieldHandler.getFieldSize(FIBFieldHandler.STSHF);
  337. }
  338. public void setFcStshf(int fcStshf)
  339. {
  340. _fieldHandler.setFieldOffset(FIBFieldHandler.STSHF, fcStshf);
  341. }
  342. public void setLcbStshf(int lcbStshf)
  343. {
  344. _fieldHandler.setFieldSize(FIBFieldHandler.STSHF, lcbStshf);
  345. }
  346. public int getFcClx()
  347. {
  348. return _fieldHandler.getFieldOffset(FIBFieldHandler.CLX);
  349. }
  350. public int getLcbClx()
  351. {
  352. return _fieldHandler.getFieldSize(FIBFieldHandler.CLX);
  353. }
  354. public void setFcClx(int fcClx)
  355. {
  356. _fieldHandler.setFieldOffset(FIBFieldHandler.CLX, fcClx);
  357. }
  358. public void setLcbClx(int lcbClx)
  359. {
  360. _fieldHandler.setFieldSize(FIBFieldHandler.CLX, lcbClx);
  361. }
  362. public int getFcPlcfbteChpx()
  363. {
  364. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFBTECHPX);
  365. }
  366. public int getLcbPlcfbteChpx()
  367. {
  368. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFBTECHPX);
  369. }
  370. public void setFcPlcfbteChpx(int fcPlcfBteChpx)
  371. {
  372. _fieldHandler.setFieldOffset(FIBFieldHandler.PLCFBTECHPX, fcPlcfBteChpx);
  373. }
  374. public void setLcbPlcfbteChpx(int lcbPlcfBteChpx)
  375. {
  376. _fieldHandler.setFieldSize(FIBFieldHandler.PLCFBTECHPX, lcbPlcfBteChpx);
  377. }
  378. public int getFcPlcfbtePapx()
  379. {
  380. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFBTEPAPX);
  381. }
  382. public int getLcbPlcfbtePapx()
  383. {
  384. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFBTEPAPX);
  385. }
  386. public void setFcPlcfbtePapx(int fcPlcfBtePapx)
  387. {
  388. _fieldHandler.setFieldOffset(FIBFieldHandler.PLCFBTEPAPX, fcPlcfBtePapx);
  389. }
  390. public void setLcbPlcfbtePapx(int lcbPlcfBtePapx)
  391. {
  392. _fieldHandler.setFieldSize(FIBFieldHandler.PLCFBTEPAPX, lcbPlcfBtePapx);
  393. }
  394. public int getFcPlcfsed()
  395. {
  396. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFSED);
  397. }
  398. public int getLcbPlcfsed()
  399. {
  400. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFSED);
  401. }
  402. public void setFcPlcfsed(int fcPlcfSed)
  403. {
  404. _fieldHandler.setFieldOffset(FIBFieldHandler.PLCFSED, fcPlcfSed);
  405. }
  406. public void setLcbPlcfsed(int lcbPlcfSed)
  407. {
  408. _fieldHandler.setFieldSize(FIBFieldHandler.PLCFSED, lcbPlcfSed);
  409. }
  410. @Deprecated
  411. public int getFcPlcfLst()
  412. {
  413. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFLST);
  414. }
  415. /**
  416. * An unsigned integer that specifies an offset in the Table Stream. A
  417. * PlfLst that contains list formatting information begins at this offset.
  418. * An array of LVLs is appended to the PlfLst. lcbPlfLst does not account
  419. * for the array of LVLs. The size of the array of LVLs is specified by the
  420. * LSTFs in PlfLst. For each LSTF whose fSimpleList is set to 0x1, there is
  421. * one LVL in the array of LVLs that specifies the level formatting of the
  422. * single level in the list which corresponds to the LSTF. And, for each
  423. * LSTF whose fSimpleList is set to 0x0, there are 9 LVLs in the array of
  424. * LVLs that specify the level formatting of the respective levels in the
  425. * list which corresponds to the LSTF. This array of LVLs is in the same
  426. * respective order as the LSTFs in PlfLst. If lcbPlfLst is 0, fcPlfLst is
  427. * undefined and MUST be ignored.
  428. * <p>
  429. * Quote from
  430. * "[MS-DOC] -- v20110315, Word (.doc) Binary File Format; page 76 / 621"
  431. */
  432. public int getFcPlfLst()
  433. {
  434. return _fieldHandler.getFieldOffset( FIBFieldHandler.PLFLST );
  435. }
  436. @Deprecated
  437. public int getLcbPlcfLst()
  438. {
  439. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFLST);
  440. }
  441. public int getLcbPlfLst()
  442. {
  443. return _fieldHandler.getFieldSize( FIBFieldHandler.PLFLST );
  444. }
  445. @Deprecated
  446. public void setFcPlcfLst( int fcPlcfLst )
  447. {
  448. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFLST, fcPlcfLst );
  449. }
  450. public void setFcPlfLst( int fcPlfLst )
  451. {
  452. _fieldHandler.setFieldOffset( FIBFieldHandler.PLFLST, fcPlfLst );
  453. }
  454. @Deprecated
  455. public void setLcbPlcfLst( int lcbPlcfLst )
  456. {
  457. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFLST, lcbPlcfLst );
  458. }
  459. public void setLcbPlfLst( int lcbPlfLst )
  460. {
  461. _fieldHandler.setFieldSize( FIBFieldHandler.PLFLST, lcbPlfLst );
  462. }
  463. /**
  464. * An unsigned integer that specifies an offset in the Table Stream. A
  465. * PlfLfo that contains list formatting override information begins at this
  466. * offset. If lcbPlfLfo is zero, fcPlfLfo is undefined and MUST be ignored.
  467. * <p>
  468. * Quote from
  469. * "[MS-DOC] -- v20110315, Word (.doc) Binary File Format; page 76 / 621"
  470. */
  471. public int getFcPlfLfo()
  472. {
  473. return _fieldHandler.getFieldOffset( FIBFieldHandler.PLFLFO );
  474. }
  475. public int getLcbPlfLfo()
  476. {
  477. return _fieldHandler.getFieldSize(FIBFieldHandler.PLFLFO);
  478. }
  479. /**
  480. * @return Offset in table stream of the STTBF that records bookmark names
  481. * in the main document
  482. */
  483. public int getFcSttbfbkmk()
  484. {
  485. return _fieldHandler.getFieldOffset( FIBFieldHandler.STTBFBKMK );
  486. }
  487. public void setFcSttbfbkmk( int offset )
  488. {
  489. _fieldHandler.setFieldOffset( FIBFieldHandler.STTBFBKMK, offset );
  490. }
  491. /**
  492. * @return Count of bytes in Sttbfbkmk
  493. */
  494. public int getLcbSttbfbkmk()
  495. {
  496. return _fieldHandler.getFieldSize( FIBFieldHandler.STTBFBKMK );
  497. }
  498. public void setLcbSttbfbkmk( int length )
  499. {
  500. _fieldHandler.setFieldSize( FIBFieldHandler.STTBFBKMK, length );
  501. }
  502. /**
  503. * @return Offset in table stream of the PLCF that records the beginning CP
  504. * offsets of bookmarks in the main document. See BKF structure
  505. * definition.
  506. */
  507. public int getFcPlcfbkf()
  508. {
  509. return _fieldHandler.getFieldOffset( FIBFieldHandler.PLCFBKF );
  510. }
  511. public void setFcPlcfbkf( int offset )
  512. {
  513. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFBKF, offset );
  514. }
  515. /**
  516. * @return Count of bytes in Plcfbkf
  517. */
  518. public int getLcbPlcfbkf()
  519. {
  520. return _fieldHandler.getFieldSize( FIBFieldHandler.PLCFBKF );
  521. }
  522. public void setLcbPlcfbkf( int length )
  523. {
  524. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFBKF, length );
  525. }
  526. /**
  527. * @return Offset in table stream of the PLCF that records the ending CP
  528. * offsets of bookmarks recorded in the main document. No structure
  529. * is stored in this PLCF.
  530. */
  531. public int getFcPlcfbkl()
  532. {
  533. return _fieldHandler.getFieldOffset( FIBFieldHandler.PLCFBKL );
  534. }
  535. public void setFcPlcfbkl( int offset )
  536. {
  537. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFBKL, offset );
  538. }
  539. /**
  540. * @return Count of bytes in Plcfbkl
  541. */
  542. public int getLcbPlcfbkl()
  543. {
  544. return _fieldHandler.getFieldSize( FIBFieldHandler.PLCFBKL );
  545. }
  546. public void setLcbPlcfbkl( int length )
  547. {
  548. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFBKL, length );
  549. }
  550. public void setFcPlfLfo(int fcPlfLfo)
  551. {
  552. _fieldHandler.setFieldOffset(FIBFieldHandler.PLFLFO, fcPlfLfo);
  553. }
  554. public void setLcbPlfLfo(int lcbPlfLfo)
  555. {
  556. _fieldHandler.setFieldSize(FIBFieldHandler.PLFLFO, lcbPlfLfo);
  557. }
  558. public int getFcSttbfffn()
  559. {
  560. return _fieldHandler.getFieldOffset(FIBFieldHandler.STTBFFFN);
  561. }
  562. public int getLcbSttbfffn()
  563. {
  564. return _fieldHandler.getFieldSize(FIBFieldHandler.STTBFFFN);
  565. }
  566. public void setFcSttbfffn(int fcSttbFffn)
  567. {
  568. _fieldHandler.setFieldOffset(FIBFieldHandler.STTBFFFN, fcSttbFffn);
  569. }
  570. public void setLcbSttbfffn(int lcbSttbFffn)
  571. {
  572. _fieldHandler.setFieldSize(FIBFieldHandler.STTBFFFN, lcbSttbFffn);
  573. }
  574. public int getFcSttbfRMark()
  575. {
  576. return _fieldHandler.getFieldOffset(FIBFieldHandler.STTBFRMARK);
  577. }
  578. public int getLcbSttbfRMark()
  579. {
  580. return _fieldHandler.getFieldSize(FIBFieldHandler.STTBFRMARK);
  581. }
  582. public void setFcSttbfRMark(int fcSttbfRMark)
  583. {
  584. _fieldHandler.setFieldOffset(FIBFieldHandler.STTBFRMARK, fcSttbfRMark);
  585. }
  586. public void setLcbSttbfRMark(int lcbSttbfRMark)
  587. {
  588. _fieldHandler.setFieldSize(FIBFieldHandler.STTBFRMARK, lcbSttbfRMark);
  589. }
  590. /**
  591. * Return the offset to the PlcfHdd, in the table stream,
  592. * i.e. fcPlcfHdd
  593. */
  594. public int getPlcfHddOffset() {
  595. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFHDD);
  596. }
  597. /**
  598. * Return the size of the PlcfHdd, in the table stream,
  599. * i.e. lcbPlcfHdd
  600. */
  601. public int getPlcfHddSize() {
  602. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFHDD);
  603. }
  604. public void setPlcfHddOffset(int fcPlcfHdd) {
  605. _fieldHandler.setFieldOffset(FIBFieldHandler.PLCFHDD, fcPlcfHdd);
  606. }
  607. public void setPlcfHddSize(int lcbPlcfHdd) {
  608. _fieldHandler.setFieldSize(FIBFieldHandler.PLCFHDD, lcbPlcfHdd);
  609. }
  610. public int getFcSttbSavedBy()
  611. {
  612. return _fieldHandler.getFieldOffset(FIBFieldHandler.STTBSAVEDBY);
  613. }
  614. public int getLcbSttbSavedBy()
  615. {
  616. return _fieldHandler.getFieldSize(FIBFieldHandler.STTBSAVEDBY);
  617. }
  618. public void setFcSttbSavedBy(int fcSttbSavedBy)
  619. {
  620. _fieldHandler.setFieldOffset(FIBFieldHandler.STTBSAVEDBY, fcSttbSavedBy);
  621. }
  622. public void setLcbSttbSavedBy(int fcSttbSavedBy)
  623. {
  624. _fieldHandler.setFieldSize(FIBFieldHandler.STTBSAVEDBY, fcSttbSavedBy);
  625. }
  626. public int getModifiedLow()
  627. {
  628. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLFLFO);
  629. }
  630. public int getModifiedHigh()
  631. {
  632. return _fieldHandler.getFieldSize(FIBFieldHandler.PLFLFO);
  633. }
  634. public void setModifiedLow(int modifiedLow)
  635. {
  636. _fieldHandler.setFieldOffset(FIBFieldHandler.PLFLFO, modifiedLow);
  637. }
  638. public void setModifiedHigh(int modifiedHigh)
  639. {
  640. _fieldHandler.setFieldSize(FIBFieldHandler.PLFLFO, modifiedHigh);
  641. }
  642. /**
  643. * How many bytes of the main stream contain real data.
  644. */
  645. public int getCbMac()
  646. {
  647. return _fibRgLw.getCbMac();
  648. }
  649. /**
  650. * Updates the count of the number of bytes in the
  651. * main stream which contain real data
  652. */
  653. public void setCbMac( int cbMac )
  654. {
  655. _fibRgLw.setCbMac( cbMac );
  656. }
  657. /**
  658. * @return length of specified subdocument text stream in characters
  659. */
  660. public int getSubdocumentTextStreamLength( SubdocumentType type )
  661. {
  662. if ( type == null )
  663. throw new IllegalArgumentException( "argument 'type' is null" );
  664. return _fibRgLw.getSubdocumentTextStreamLength( type );
  665. }
  666. public void setSubdocumentTextStreamLength( SubdocumentType type, int length )
  667. {
  668. if ( type == null )
  669. throw new IllegalArgumentException( "argument 'type' is null" );
  670. if ( length < 0 )
  671. throw new IllegalArgumentException(
  672. "Subdocument length can't be less than 0 (passed value is "
  673. + length + "). " + "If there is no subdocument "
  674. + "length must be set to zero." );
  675. _fibRgLw.setSubdocumentTextStreamLength( type, length );
  676. }
  677. public void clearOffsetsSizes()
  678. {
  679. _fieldHandler.clearFields();
  680. }
  681. public int getFieldsPlcfOffset( FieldsDocumentPart part )
  682. {
  683. return _fieldHandler.getFieldOffset( part.getFibFieldsField() );
  684. }
  685. public int getFieldsPlcfLength( FieldsDocumentPart part )
  686. {
  687. return _fieldHandler.getFieldSize( part.getFibFieldsField() );
  688. }
  689. public void setFieldsPlcfOffset( FieldsDocumentPart part, int offset )
  690. {
  691. _fieldHandler.setFieldOffset( part.getFibFieldsField(), offset );
  692. }
  693. public void setFieldsPlcfLength( FieldsDocumentPart part, int length )
  694. {
  695. _fieldHandler.setFieldSize( part.getFibFieldsField(), length );
  696. }
  697. @Deprecated
  698. public int getFcPlcffldAtn()
  699. {
  700. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDATN);
  701. }
  702. @Deprecated
  703. public int getLcbPlcffldAtn()
  704. {
  705. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDATN);
  706. }
  707. @Deprecated
  708. public void setFcPlcffldAtn( int offset )
  709. {
  710. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDATN, offset );
  711. }
  712. @Deprecated
  713. public void setLcbPlcffldAtn( int size )
  714. {
  715. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDATN, size );
  716. }
  717. @Deprecated
  718. public int getFcPlcffldEdn()
  719. {
  720. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDEDN);
  721. }
  722. @Deprecated
  723. public int getLcbPlcffldEdn()
  724. {
  725. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDEDN);
  726. }
  727. @Deprecated
  728. public void setFcPlcffldEdn( int offset )
  729. {
  730. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDEDN, offset );
  731. }
  732. @Deprecated
  733. public void setLcbPlcffldEdn( int size )
  734. {
  735. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDEDN, size );
  736. }
  737. @Deprecated
  738. public int getFcPlcffldFtn()
  739. {
  740. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDFTN);
  741. }
  742. @Deprecated
  743. public int getLcbPlcffldFtn()
  744. {
  745. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDFTN);
  746. }
  747. @Deprecated
  748. public void setFcPlcffldFtn( int offset )
  749. {
  750. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDFTN, offset );
  751. }
  752. @Deprecated
  753. public void setLcbPlcffldFtn( int size )
  754. {
  755. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDFTN, size );
  756. }
  757. @Deprecated
  758. public int getFcPlcffldHdr()
  759. {
  760. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDHDR);
  761. }
  762. @Deprecated
  763. public int getLcbPlcffldHdr()
  764. {
  765. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDHDR);
  766. }
  767. @Deprecated
  768. public void setFcPlcffldHdr( int offset )
  769. {
  770. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDHDR, offset );
  771. }
  772. @Deprecated
  773. public void setLcbPlcffldHdr( int size )
  774. {
  775. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDHDR, size );
  776. }
  777. @Deprecated
  778. public int getFcPlcffldHdrtxbx()
  779. {
  780. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDHDRTXBX);
  781. }
  782. @Deprecated
  783. public int getLcbPlcffldHdrtxbx()
  784. {
  785. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDHDRTXBX);
  786. }
  787. @Deprecated
  788. public void setFcPlcffldHdrtxbx( int offset )
  789. {
  790. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDHDRTXBX, offset );
  791. }
  792. @Deprecated
  793. public void setLcbPlcffldHdrtxbx( int size )
  794. {
  795. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDHDRTXBX, size );
  796. }
  797. @Deprecated
  798. public int getFcPlcffldMom()
  799. {
  800. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDMOM);
  801. }
  802. @Deprecated
  803. public int getLcbPlcffldMom()
  804. {
  805. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDMOM);
  806. }
  807. @Deprecated
  808. public void setFcPlcffldMom( int offset )
  809. {
  810. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDMOM, offset );
  811. }
  812. @Deprecated
  813. public void setLcbPlcffldMom( int size )
  814. {
  815. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDMOM, size );
  816. }
  817. @Deprecated
  818. public int getFcPlcffldTxbx()
  819. {
  820. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDTXBX);
  821. }
  822. @Deprecated
  823. public int getLcbPlcffldTxbx()
  824. {
  825. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDTXBX);
  826. }
  827. @Deprecated
  828. public void setFcPlcffldTxbx( int offset )
  829. {
  830. _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDTXBX, offset );
  831. }
  832. @Deprecated
  833. public void setLcbPlcffldTxbx( int size )
  834. {
  835. _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDTXBX, size );
  836. }
  837. public int getFSPAPlcfOffset( FSPADocumentPart part )
  838. {
  839. return _fieldHandler.getFieldOffset( part.getFibFieldsField() );
  840. }
  841. public int getFSPAPlcfLength( FSPADocumentPart part )
  842. {
  843. return _fieldHandler.getFieldSize( part.getFibFieldsField() );
  844. }
  845. public void setFSPAPlcfOffset( FSPADocumentPart part, int offset )
  846. {
  847. _fieldHandler.setFieldOffset( part.getFibFieldsField(), offset );
  848. }
  849. public void setFSPAPlcfLength( FSPADocumentPart part, int length )
  850. {
  851. _fieldHandler.setFieldSize( part.getFibFieldsField(), length );
  852. }
  853. @Deprecated
  854. public int getFcPlcspaMom()
  855. {
  856. return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCSPAMOM);
  857. }
  858. @Deprecated
  859. public int getLcbPlcspaMom()
  860. {
  861. return _fieldHandler.getFieldSize(FIBFieldHandler.PLCSPAMOM);
  862. }
  863. public int getFcDggInfo()
  864. {
  865. return _fieldHandler.getFieldOffset(FIBFieldHandler.DGGINFO);
  866. }
  867. public int getLcbDggInfo()
  868. {
  869. return _fieldHandler.getFieldSize(FIBFieldHandler.DGGINFO);
  870. }
  871. public int getNotesDescriptorsOffset( NoteType noteType )
  872. {
  873. return _fieldHandler.getFieldOffset( noteType
  874. .getFibDescriptorsFieldIndex() );
  875. }
  876. public void setNotesDescriptorsOffset( NoteType noteType, int offset )
  877. {
  878. _fieldHandler.setFieldOffset( noteType.getFibDescriptorsFieldIndex(),
  879. offset );
  880. }
  881. public int getNotesDescriptorsSize( NoteType noteType )
  882. {
  883. return _fieldHandler.getFieldSize( noteType
  884. .getFibDescriptorsFieldIndex() );
  885. }
  886. public void setNotesDescriptorsSize( NoteType noteType, int offset )
  887. {
  888. _fieldHandler.setFieldSize( noteType.getFibDescriptorsFieldIndex(),
  889. offset );
  890. }
  891. public int getNotesTextPositionsOffset( NoteType noteType )
  892. {
  893. return _fieldHandler.getFieldOffset( noteType
  894. .getFibTextPositionsFieldIndex() );
  895. }
  896. public void setNotesTextPositionsOffset( NoteType noteType, int offset )
  897. {
  898. _fieldHandler.setFieldOffset( noteType.getFibTextPositionsFieldIndex(),
  899. offset );
  900. }
  901. public int getNotesTextPositionsSize( NoteType noteType )
  902. {
  903. return _fieldHandler.getFieldSize( noteType
  904. .getFibTextPositionsFieldIndex() );
  905. }
  906. public void setNotesTextPositionsSize( NoteType noteType, int offset )
  907. {
  908. _fieldHandler.setFieldSize( noteType.getFibTextPositionsFieldIndex(),
  909. offset );
  910. }
  911. public void writeTo( byte[] mainStream, ByteArrayOutputStream tableStream )
  912. throws IOException
  913. {
  914. _cbRgFcLcb = _fieldHandler.getFieldsCount();
  915. _fibBase.serialize( mainStream, 0 );
  916. int offset = FibBaseAbstractType.getSize();
  917. LittleEndian.putUShort( mainStream, offset, _csw );
  918. offset += LittleEndianConsts.SHORT_SIZE;
  919. _fibRgW.serialize( mainStream, offset );
  920. offset += FibRgW97AbstractType.getSize();
  921. LittleEndian.putUShort( mainStream, offset, _cslw );
  922. offset += LittleEndianConsts.SHORT_SIZE;
  923. ( (FibRgLw97) _fibRgLw ).serialize( mainStream, offset );
  924. offset += FibRgLw97.getSize();
  925. LittleEndian.putUShort( mainStream, offset, _cbRgFcLcb );
  926. offset += LittleEndianConsts.SHORT_SIZE;
  927. _fieldHandler.writeTo( mainStream, offset, tableStream );
  928. offset += _cbRgFcLcb * LittleEndianConsts.INT_SIZE * 2;
  929. LittleEndian.putUShort( mainStream, offset, _cswNew );
  930. offset += LittleEndianConsts.SHORT_SIZE;
  931. if ( _cswNew != 0 )
  932. {
  933. LittleEndian.putUShort( mainStream, offset, _nFibNew );
  934. offset += LittleEndianConsts.SHORT_SIZE;
  935. System.arraycopy( _fibRgCswNew, 0, mainStream, offset,
  936. _fibRgCswNew.length );
  937. offset += _fibRgCswNew.length;
  938. }
  939. }
  940. public int getSize()
  941. {
  942. return FibBaseAbstractType.getSize() + LittleEndianConsts.SHORT_SIZE + FibRgW97AbstractType.getSize()
  943. + LittleEndianConsts.SHORT_SIZE + FibRgLw97.getSize()
  944. + LittleEndianConsts.SHORT_SIZE + _fieldHandler.sizeInBytes();
  945. }
  946. public FibBase getFibBase()
  947. {
  948. return _fibBase;
  949. }
  950. }