1128 lines
34 KiB
Java
1128 lines
34 KiB
Java
/* ====================================================================
|
|
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.io.IOException;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Modifier;
|
|
import java.util.HashSet;
|
|
import java.util.Locale;
|
|
|
|
import org.apache.poi.EncryptedDocumentException;
|
|
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
|
|
import org.apache.poi.util.Internal;
|
|
import org.apache.poi.util.LittleEndian;
|
|
import org.apache.poi.util.POILogFactory;
|
|
import org.apache.poi.util.POILogger;
|
|
|
|
/**
|
|
* <p>The File Information Block (FIB). Holds pointers
|
|
* to various bits of the file, and lots of flags which
|
|
* specify properties of the document.<p>
|
|
* <ul>
|
|
* <li>The {@link FibBase} class, holds the first 32 bytes.</li>
|
|
* <li>The next part, the fibRgW / FibRgW97, is handled by the {@link FibRgW97}.</li>
|
|
* <li>The next part, the fibRgLw / FibRgLw97, is handled by the {@link FibRgLw97}.</li>
|
|
* <li>Finally, the rest of the fields are handled by the {@link FIBFieldHandler}.</li>
|
|
* </ul>
|
|
*/
|
|
@Internal
|
|
public final class FileInformationBlock
|
|
{
|
|
public static final POILogger logger = POILogFactory
|
|
.getLogger( FileInformationBlock.class );
|
|
|
|
private FibBase _fibBase;
|
|
private int _csw;
|
|
private FibRgW97 _fibRgW;
|
|
private int _cslw;
|
|
private FibRgLw _fibRgLw;
|
|
private int _cbRgFcLcb;
|
|
private FIBFieldHandler _fieldHandler;
|
|
private int _cswNew;
|
|
private int _nFibNew;
|
|
private byte[] _fibRgCswNew;
|
|
|
|
/** Creates a new instance of FileInformationBlock */
|
|
public FileInformationBlock( byte[] mainDocument )
|
|
{
|
|
int offset = 0;
|
|
|
|
_fibBase = new FibBase( mainDocument, offset );
|
|
offset = FibBase.getSize();
|
|
assert offset == 32;
|
|
|
|
if ( _fibBase.isFEncrypted() )
|
|
{
|
|
throw new EncryptedDocumentException(
|
|
"Cannot process encrypted word file" );
|
|
}
|
|
|
|
_csw = LittleEndian.getUShort( mainDocument, offset );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
assert offset == 34;
|
|
|
|
_fibRgW = new FibRgW97( mainDocument, offset );
|
|
offset += FibRgW97.getSize();
|
|
assert offset == 62;
|
|
|
|
_cslw = LittleEndian.getUShort( mainDocument, offset );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
assert offset == 64;
|
|
|
|
if ( _fibBase.getNFib() < 105 )
|
|
{
|
|
_fibRgLw = new FibRgLw95( mainDocument, offset );
|
|
offset += FibRgLw97.getSize();
|
|
|
|
// magic number, run tests after changes
|
|
_cbRgFcLcb = 74;
|
|
|
|
// skip fibRgFcLcbBlob (read later at fillVariableFields)
|
|
offset += _cbRgFcLcb * LittleEndian.INT_SIZE * 2;
|
|
|
|
_cswNew = LittleEndian.getUShort( mainDocument, offset );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
|
|
_cswNew = 0;
|
|
_nFibNew = -1;
|
|
_fibRgCswNew = new byte[0];
|
|
|
|
return;
|
|
}
|
|
|
|
_fibRgLw = new FibRgLw97( mainDocument, offset );
|
|
offset += FibRgLw97.getSize();
|
|
assert offset == 152;
|
|
|
|
_cbRgFcLcb = LittleEndian.getUShort( mainDocument, offset );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
assert offset == 154;
|
|
|
|
// skip fibRgFcLcbBlob (read later at fillVariableFields)
|
|
offset += _cbRgFcLcb * LittleEndian.INT_SIZE * 2;
|
|
|
|
_cswNew = LittleEndian.getUShort( mainDocument, offset );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
|
|
if ( _cswNew != 0 )
|
|
{
|
|
_nFibNew = LittleEndian.getUShort( mainDocument, offset );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
|
|
// first short is already read as _nFibNew
|
|
final int fibRgCswNewLength = ( _cswNew - 1 )
|
|
* LittleEndian.SHORT_SIZE;
|
|
_fibRgCswNew = new byte[fibRgCswNewLength];
|
|
LittleEndian.getByteArray( mainDocument, offset, fibRgCswNewLength );
|
|
offset += fibRgCswNewLength;
|
|
}
|
|
else
|
|
{
|
|
_nFibNew = -1;
|
|
_fibRgCswNew = new byte[0];
|
|
}
|
|
|
|
assertCbRgFcLcb();
|
|
assertCswNew();
|
|
}
|
|
|
|
private void assertCbRgFcLcb()
|
|
{
|
|
int nfib = getNFib();
|
|
String nfibHex = String.format(Locale.ROOT, "%04X", nfib);
|
|
|
|
// Note - CommonCrawl shows there's more variation in these than
|
|
// the documentation suggests, so accept common clusters around
|
|
// the "correct" value as well
|
|
switch ( nfib )
|
|
{
|
|
case 0x0071:
|
|
// Found in CommonCrawl corpus but not in the docs...
|
|
break;
|
|
case 0x00BE:
|
|
case 0x00BF:
|
|
case 0x00C0:
|
|
case 0x00C1: // Docs "official"
|
|
case 0x00C2:
|
|
case 0x00C3:
|
|
assertCbRgFcLcb(nfibHex, 0x005D, "0x005D", _cbRgFcLcb );
|
|
break;
|
|
case 0x00D8:
|
|
case 0x00D9: // Docs "official"
|
|
assertCbRgFcLcb(nfibHex, 0x006C, "0x006C", _cbRgFcLcb );
|
|
break;
|
|
case 0x0101:
|
|
assertCbRgFcLcb( "0x0101", 0x0088, "0x0088", _cbRgFcLcb );
|
|
break;
|
|
// TODO Is CommonCrawl 265 = 0x109 the one above or below?
|
|
case 0x010B:
|
|
case 0x010C: // Docs "official"
|
|
assertCbRgFcLcb(nfibHex, 0x00A4, "0x00A4", _cbRgFcLcb );
|
|
break;
|
|
case 0x0112:
|
|
assertCbRgFcLcb( "0x0112", 0x00B7, "0x00B7", _cbRgFcLcb );
|
|
break;
|
|
default:
|
|
/* The Word spec has a much smaller list of "valid" values
|
|
* to what the large CommonCrawl corpus contains!
|
|
*/
|
|
logger.log(POILogger.WARN, "Invalid file format version number: " + nfib + "("+nfibHex+")");
|
|
}
|
|
}
|
|
|
|
private static void assertCbRgFcLcb( final String strNFib,
|
|
final int expectedCbRgFcLcb, final String strCbRgFcLcb,
|
|
final int cbRgFcLcb )
|
|
{
|
|
if ( cbRgFcLcb == expectedCbRgFcLcb )
|
|
return;
|
|
|
|
logger.log( POILogger.WARN, "Since FIB.nFib == ", strNFib,
|
|
" value of FIB.cbRgFcLcb MUST be ", strCbRgFcLcb + ", not 0x",
|
|
Integer.toHexString( cbRgFcLcb ) );
|
|
}
|
|
|
|
private void assertCswNew()
|
|
{
|
|
switch ( getNFib() )
|
|
{
|
|
case 0x00C1:
|
|
assertCswNew( "0x00C1", 0x0000, "0x0000", _cswNew );
|
|
break;
|
|
case 0x00D9:
|
|
assertCswNew( "0x00D9", 0x0002, "0x0002", _cswNew );
|
|
break;
|
|
case 0x0101:
|
|
assertCswNew( "0x0101", 0x0002, "0x0002", _cswNew );
|
|
break;
|
|
case 0x010C:
|
|
assertCswNew( "0x010C", 0x0002, "0x0002", _cswNew );
|
|
break;
|
|
case 0x0112:
|
|
assertCswNew( "0x0112", 0x0005, "0x0005", _cswNew );
|
|
break;
|
|
default:
|
|
logger.log(POILogger.WARN, "Invalid file format version number: " + getNFib());
|
|
}
|
|
}
|
|
|
|
private static void assertCswNew( final String strNFib,
|
|
final int expectedCswNew, final String strExpectedCswNew,
|
|
final int cswNew )
|
|
{
|
|
if ( cswNew == expectedCswNew )
|
|
return;
|
|
|
|
logger.log( POILogger.WARN, "Since FIB.nFib == ", strNFib,
|
|
" value of FIB.cswNew MUST be ",
|
|
strExpectedCswNew + ", not 0x", Integer.toHexString( cswNew ) );
|
|
}
|
|
|
|
public void fillVariableFields( byte[] mainDocument, byte[] tableStream )
|
|
{
|
|
/*
|
|
* Listed fields won't be treat as UnhandledDataStructure. For all other
|
|
* fields FIBFieldHandler will load it content into
|
|
* UnhandledDataStructure and save them on save.
|
|
*/
|
|
HashSet<Integer> knownFieldSet = new HashSet<Integer>();
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STSHF ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.CLX ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.DOP ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBTECHPX ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBTEPAPX ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFSED ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLFLST ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLFLFO ) );
|
|
|
|
// field info
|
|
for ( FieldsDocumentPart part : FieldsDocumentPart.values() )
|
|
knownFieldSet.add( Integer.valueOf( part.getFibFieldsField() ) );
|
|
|
|
// bookmarks
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBKF ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBKL ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBFBKMK ) );
|
|
|
|
// notes
|
|
for ( NoteType noteType : NoteType.values() )
|
|
{
|
|
knownFieldSet.add( Integer.valueOf( noteType
|
|
.getFibDescriptorsFieldIndex() ) );
|
|
knownFieldSet.add( Integer.valueOf( noteType
|
|
.getFibTextPositionsFieldIndex() ) );
|
|
}
|
|
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBFFFN ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBFRMARK ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBSAVEDBY ) );
|
|
knownFieldSet.add( Integer.valueOf( FIBFieldHandler.MODIFIED ) );
|
|
|
|
_fieldHandler = new FIBFieldHandler( mainDocument, 154, _cbRgFcLcb,
|
|
tableStream, knownFieldSet, true );
|
|
}
|
|
|
|
@Override
|
|
public String toString()
|
|
{
|
|
StringBuilder stringBuilder = new StringBuilder( );
|
|
stringBuilder.append( _fibBase );
|
|
stringBuilder.append( "[FIB2]\n" );
|
|
stringBuilder.append( "\tSubdocuments info:\n" );
|
|
for ( SubdocumentType type : SubdocumentType.values() )
|
|
{
|
|
stringBuilder.append( "\t\t" );
|
|
stringBuilder.append( type );
|
|
stringBuilder.append( " has length of " );
|
|
stringBuilder.append( getSubdocumentTextStreamLength( type ) );
|
|
stringBuilder.append( " char(s)\n" );
|
|
}
|
|
stringBuilder.append( "\tFields PLCF info:\n" );
|
|
for ( FieldsDocumentPart part : FieldsDocumentPart.values() )
|
|
{
|
|
stringBuilder.append( "\t\t" );
|
|
stringBuilder.append( part );
|
|
stringBuilder.append( ": PLCF starts at " );
|
|
stringBuilder.append( getFieldsPlcfOffset( part ) );
|
|
stringBuilder.append( " and have length of " );
|
|
stringBuilder.append( getFieldsPlcfLength( part ) );
|
|
stringBuilder.append( "\n" );
|
|
}
|
|
stringBuilder.append( "\tNotes PLCF info:\n" );
|
|
for ( NoteType noteType : NoteType.values() )
|
|
{
|
|
stringBuilder.append( "\t\t" );
|
|
stringBuilder.append( noteType );
|
|
stringBuilder.append( ": descriptions starts " );
|
|
stringBuilder.append( getNotesDescriptorsOffset( noteType ) );
|
|
stringBuilder.append( " and have length of " );
|
|
stringBuilder.append( getNotesDescriptorsSize( noteType ) );
|
|
stringBuilder.append( " bytes\n" );
|
|
stringBuilder.append( "\t\t" );
|
|
stringBuilder.append( noteType );
|
|
stringBuilder.append( ": text positions starts " );
|
|
stringBuilder.append( getNotesTextPositionsOffset( noteType ) );
|
|
stringBuilder.append( " and have length of " );
|
|
stringBuilder.append( getNotesTextPositionsSize( noteType ) );
|
|
stringBuilder.append( " bytes\n" );
|
|
}
|
|
stringBuilder.append( _fieldHandler );
|
|
try
|
|
{
|
|
stringBuilder.append( "\tJava reflection info:\n" );
|
|
for ( Method method : FileInformationBlock.class.getMethods() )
|
|
{
|
|
if ( !method.getName().startsWith( "get" )
|
|
|| !Modifier.isPublic( method.getModifiers() )
|
|
|| Modifier.isStatic( method.getModifiers() )
|
|
|| method.getParameterTypes().length > 0 )
|
|
continue;
|
|
stringBuilder.append( "\t\t" );
|
|
stringBuilder.append( method.getName() );
|
|
stringBuilder.append( " => " );
|
|
stringBuilder.append( method.invoke( this ) );
|
|
stringBuilder.append( "\n" );
|
|
}
|
|
}
|
|
catch ( Exception exc )
|
|
{
|
|
stringBuilder.append("(exc: ").append(exc.getMessage()).append(")");
|
|
}
|
|
stringBuilder.append( "[/FIB2]\n" );
|
|
return stringBuilder.toString();
|
|
}
|
|
|
|
public int getNFib()
|
|
{
|
|
if ( _cswNew == 0 )
|
|
return _fibBase.getNFib();
|
|
|
|
return _nFibNew;
|
|
}
|
|
|
|
public int getFcDop()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.DOP);
|
|
}
|
|
|
|
public void setFcDop(int fcDop)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.DOP, fcDop);
|
|
}
|
|
|
|
public int getLcbDop()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.DOP);
|
|
}
|
|
|
|
public void setLcbDop(int lcbDop)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.DOP, lcbDop);
|
|
}
|
|
|
|
public int getFcStshf()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.STSHF);
|
|
}
|
|
|
|
public int getLcbStshf()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.STSHF);
|
|
}
|
|
|
|
public void setFcStshf(int fcStshf)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.STSHF, fcStshf);
|
|
}
|
|
|
|
public void setLcbStshf(int lcbStshf)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.STSHF, lcbStshf);
|
|
}
|
|
|
|
public int getFcClx()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.CLX);
|
|
}
|
|
|
|
public int getLcbClx()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.CLX);
|
|
}
|
|
|
|
public void setFcClx(int fcClx)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.CLX, fcClx);
|
|
}
|
|
|
|
public void setLcbClx(int lcbClx)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.CLX, lcbClx);
|
|
}
|
|
|
|
public int getFcPlcfbteChpx()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFBTECHPX);
|
|
}
|
|
|
|
public int getLcbPlcfbteChpx()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFBTECHPX);
|
|
}
|
|
|
|
public void setFcPlcfbteChpx(int fcPlcfBteChpx)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.PLCFBTECHPX, fcPlcfBteChpx);
|
|
}
|
|
|
|
public void setLcbPlcfbteChpx(int lcbPlcfBteChpx)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.PLCFBTECHPX, lcbPlcfBteChpx);
|
|
}
|
|
|
|
public int getFcPlcfbtePapx()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFBTEPAPX);
|
|
}
|
|
|
|
public int getLcbPlcfbtePapx()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFBTEPAPX);
|
|
}
|
|
|
|
public void setFcPlcfbtePapx(int fcPlcfBtePapx)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.PLCFBTEPAPX, fcPlcfBtePapx);
|
|
}
|
|
|
|
public void setLcbPlcfbtePapx(int lcbPlcfBtePapx)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.PLCFBTEPAPX, lcbPlcfBtePapx);
|
|
}
|
|
|
|
public int getFcPlcfsed()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFSED);
|
|
}
|
|
|
|
public int getLcbPlcfsed()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFSED);
|
|
}
|
|
|
|
public void setFcPlcfsed(int fcPlcfSed)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.PLCFSED, fcPlcfSed);
|
|
}
|
|
|
|
public void setLcbPlcfsed(int lcbPlcfSed)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.PLCFSED, lcbPlcfSed);
|
|
}
|
|
|
|
@Deprecated
|
|
public int getFcPlcfLst()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFLST);
|
|
}
|
|
|
|
/**
|
|
* An unsigned integer that specifies an offset in the Table Stream. A
|
|
* PlfLst that contains list formatting information begins at this offset.
|
|
* An array of LVLs is appended to the PlfLst. lcbPlfLst does not account
|
|
* for the array of LVLs. The size of the array of LVLs is specified by the
|
|
* LSTFs in PlfLst. For each LSTF whose fSimpleList is set to 0x1, there is
|
|
* one LVL in the array of LVLs that specifies the level formatting of the
|
|
* single level in the list which corresponds to the LSTF. And, for each
|
|
* LSTF whose fSimpleList is set to 0x0, there are 9 LVLs in the array of
|
|
* LVLs that specify the level formatting of the respective levels in the
|
|
* list which corresponds to the LSTF. This array of LVLs is in the same
|
|
* respective order as the LSTFs in PlfLst. If lcbPlfLst is 0, fcPlfLst is
|
|
* undefined and MUST be ignored.
|
|
* <p>
|
|
* Quote from
|
|
* "[MS-DOC] -- v20110315, Word (.doc) Binary File Format; page 76 / 621"
|
|
*/
|
|
public int getFcPlfLst()
|
|
{
|
|
return _fieldHandler.getFieldOffset( FIBFieldHandler.PLFLST );
|
|
}
|
|
|
|
@Deprecated
|
|
public int getLcbPlcfLst()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFLST);
|
|
}
|
|
|
|
public int getLcbPlfLst()
|
|
{
|
|
return _fieldHandler.getFieldSize( FIBFieldHandler.PLFLST );
|
|
}
|
|
|
|
@Deprecated
|
|
public void setFcPlcfLst( int fcPlcfLst )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFLST, fcPlcfLst );
|
|
}
|
|
|
|
public void setFcPlfLst( int fcPlfLst )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLFLST, fcPlfLst );
|
|
}
|
|
|
|
@Deprecated
|
|
public void setLcbPlcfLst( int lcbPlcfLst )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFLST, lcbPlcfLst );
|
|
}
|
|
|
|
public void setLcbPlfLst( int lcbPlfLst )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLFLST, lcbPlfLst );
|
|
}
|
|
|
|
/**
|
|
* An unsigned integer that specifies an offset in the Table Stream. A
|
|
* PlfLfo that contains list formatting override information begins at this
|
|
* offset. If lcbPlfLfo is zero, fcPlfLfo is undefined and MUST be ignored.
|
|
* <p>
|
|
* Quote from
|
|
* "[MS-DOC] -- v20110315, Word (.doc) Binary File Format; page 76 / 621"
|
|
*/
|
|
public int getFcPlfLfo()
|
|
{
|
|
return _fieldHandler.getFieldOffset( FIBFieldHandler.PLFLFO );
|
|
}
|
|
|
|
public int getLcbPlfLfo()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLFLFO);
|
|
}
|
|
|
|
/**
|
|
* @return Offset in table stream of the STTBF that records bookmark names
|
|
* in the main document
|
|
*/
|
|
public int getFcSttbfbkmk()
|
|
{
|
|
return _fieldHandler.getFieldOffset( FIBFieldHandler.STTBFBKMK );
|
|
}
|
|
|
|
public void setFcSttbfbkmk( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.STTBFBKMK, offset );
|
|
}
|
|
|
|
/**
|
|
* @return Count of bytes in Sttbfbkmk
|
|
*/
|
|
public int getLcbSttbfbkmk()
|
|
{
|
|
return _fieldHandler.getFieldSize( FIBFieldHandler.STTBFBKMK );
|
|
}
|
|
|
|
public void setLcbSttbfbkmk( int length )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.STTBFBKMK, length );
|
|
}
|
|
|
|
/**
|
|
* @return Offset in table stream of the PLCF that records the beginning CP
|
|
* offsets of bookmarks in the main document. See BKF structure
|
|
* definition.
|
|
*/
|
|
public int getFcPlcfbkf()
|
|
{
|
|
return _fieldHandler.getFieldOffset( FIBFieldHandler.PLCFBKF );
|
|
}
|
|
|
|
public void setFcPlcfbkf( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFBKF, offset );
|
|
}
|
|
|
|
/**
|
|
* @return Count of bytes in Plcfbkf
|
|
*/
|
|
public int getLcbPlcfbkf()
|
|
{
|
|
return _fieldHandler.getFieldSize( FIBFieldHandler.PLCFBKF );
|
|
}
|
|
|
|
public void setLcbPlcfbkf( int length )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFBKF, length );
|
|
}
|
|
|
|
/**
|
|
* @return Offset in table stream of the PLCF that records the ending CP
|
|
* offsets of bookmarks recorded in the main document. No structure
|
|
* is stored in this PLCF.
|
|
*/
|
|
public int getFcPlcfbkl()
|
|
{
|
|
return _fieldHandler.getFieldOffset( FIBFieldHandler.PLCFBKL );
|
|
}
|
|
|
|
public void setFcPlcfbkl( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFBKL, offset );
|
|
}
|
|
|
|
/**
|
|
* @return Count of bytes in Plcfbkl
|
|
*/
|
|
public int getLcbPlcfbkl()
|
|
{
|
|
return _fieldHandler.getFieldSize( FIBFieldHandler.PLCFBKL );
|
|
}
|
|
|
|
public void setLcbPlcfbkl( int length )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFBKL, length );
|
|
}
|
|
|
|
public void setFcPlfLfo(int fcPlfLfo)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.PLFLFO, fcPlfLfo);
|
|
}
|
|
|
|
public void setLcbPlfLfo(int lcbPlfLfo)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.PLFLFO, lcbPlfLfo);
|
|
}
|
|
|
|
public int getFcSttbfffn()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.STTBFFFN);
|
|
}
|
|
|
|
public int getLcbSttbfffn()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.STTBFFFN);
|
|
}
|
|
|
|
public void setFcSttbfffn(int fcSttbFffn)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.STTBFFFN, fcSttbFffn);
|
|
}
|
|
|
|
public void setLcbSttbfffn(int lcbSttbFffn)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.STTBFFFN, lcbSttbFffn);
|
|
}
|
|
|
|
public int getFcSttbfRMark()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.STTBFRMARK);
|
|
}
|
|
|
|
public int getLcbSttbfRMark()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.STTBFRMARK);
|
|
}
|
|
|
|
public void setFcSttbfRMark(int fcSttbfRMark)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.STTBFRMARK, fcSttbfRMark);
|
|
}
|
|
|
|
public void setLcbSttbfRMark(int lcbSttbfRMark)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.STTBFRMARK, lcbSttbfRMark);
|
|
}
|
|
|
|
/**
|
|
* Return the offset to the PlcfHdd, in the table stream,
|
|
* i.e. fcPlcfHdd
|
|
*/
|
|
public int getPlcfHddOffset() {
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFHDD);
|
|
}
|
|
/**
|
|
* Return the size of the PlcfHdd, in the table stream,
|
|
* i.e. lcbPlcfHdd
|
|
*/
|
|
public int getPlcfHddSize() {
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFHDD);
|
|
}
|
|
public void setPlcfHddOffset(int fcPlcfHdd) {
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.PLCFHDD, fcPlcfHdd);
|
|
}
|
|
public void setPlcfHddSize(int lcbPlcfHdd) {
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.PLCFHDD, lcbPlcfHdd);
|
|
}
|
|
|
|
public int getFcSttbSavedBy()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.STTBSAVEDBY);
|
|
}
|
|
|
|
public int getLcbSttbSavedBy()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.STTBSAVEDBY);
|
|
}
|
|
|
|
public void setFcSttbSavedBy(int fcSttbSavedBy)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.STTBSAVEDBY, fcSttbSavedBy);
|
|
}
|
|
|
|
public void setLcbSttbSavedBy(int fcSttbSavedBy)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.STTBSAVEDBY, fcSttbSavedBy);
|
|
}
|
|
|
|
public int getModifiedLow()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLFLFO);
|
|
}
|
|
|
|
public int getModifiedHigh()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLFLFO);
|
|
}
|
|
|
|
public void setModifiedLow(int modifiedLow)
|
|
{
|
|
_fieldHandler.setFieldOffset(FIBFieldHandler.PLFLFO, modifiedLow);
|
|
}
|
|
|
|
public void setModifiedHigh(int modifiedHigh)
|
|
{
|
|
_fieldHandler.setFieldSize(FIBFieldHandler.PLFLFO, modifiedHigh);
|
|
}
|
|
|
|
/**
|
|
* How many bytes of the main stream contain real data.
|
|
*/
|
|
public int getCbMac()
|
|
{
|
|
return _fibRgLw.getCbMac();
|
|
}
|
|
|
|
/**
|
|
* Updates the count of the number of bytes in the
|
|
* main stream which contain real data
|
|
*/
|
|
public void setCbMac( int cbMac )
|
|
{
|
|
_fibRgLw.setCbMac( cbMac );
|
|
}
|
|
|
|
/**
|
|
* @return length of specified subdocument text stream in characters
|
|
*/
|
|
public int getSubdocumentTextStreamLength( SubdocumentType type )
|
|
{
|
|
if ( type == null )
|
|
throw new IllegalArgumentException( "argument 'type' is null" );
|
|
|
|
return _fibRgLw.getSubdocumentTextStreamLength( type );
|
|
}
|
|
|
|
public void setSubdocumentTextStreamLength( SubdocumentType type, int length )
|
|
{
|
|
if ( type == null )
|
|
throw new IllegalArgumentException( "argument 'type' is null" );
|
|
if ( length < 0 )
|
|
throw new IllegalArgumentException(
|
|
"Subdocument length can't be less than 0 (passed value is "
|
|
+ length + "). " + "If there is no subdocument "
|
|
+ "length must be set to zero." );
|
|
|
|
_fibRgLw.setSubdocumentTextStreamLength( type, length );
|
|
}
|
|
|
|
public void clearOffsetsSizes()
|
|
{
|
|
_fieldHandler.clearFields();
|
|
}
|
|
|
|
public int getFieldsPlcfOffset( FieldsDocumentPart part )
|
|
{
|
|
return _fieldHandler.getFieldOffset( part.getFibFieldsField() );
|
|
}
|
|
|
|
public int getFieldsPlcfLength( FieldsDocumentPart part )
|
|
{
|
|
return _fieldHandler.getFieldSize( part.getFibFieldsField() );
|
|
}
|
|
|
|
public void setFieldsPlcfOffset( FieldsDocumentPart part, int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( part.getFibFieldsField(), offset );
|
|
}
|
|
|
|
public void setFieldsPlcfLength( FieldsDocumentPart part, int length )
|
|
{
|
|
_fieldHandler.setFieldSize( part.getFibFieldsField(), length );
|
|
}
|
|
|
|
@Deprecated
|
|
public int getFcPlcffldAtn()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDATN);
|
|
}
|
|
|
|
@Deprecated
|
|
public int getLcbPlcffldAtn()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDATN);
|
|
}
|
|
|
|
@Deprecated
|
|
public void setFcPlcffldAtn( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDATN, offset );
|
|
}
|
|
|
|
@Deprecated
|
|
public void setLcbPlcffldAtn( int size )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDATN, size );
|
|
}
|
|
|
|
@Deprecated
|
|
public int getFcPlcffldEdn()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDEDN);
|
|
}
|
|
|
|
@Deprecated
|
|
public int getLcbPlcffldEdn()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDEDN);
|
|
}
|
|
|
|
@Deprecated
|
|
public void setFcPlcffldEdn( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDEDN, offset );
|
|
}
|
|
|
|
@Deprecated
|
|
public void setLcbPlcffldEdn( int size )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDEDN, size );
|
|
}
|
|
|
|
@Deprecated
|
|
public int getFcPlcffldFtn()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDFTN);
|
|
}
|
|
|
|
@Deprecated
|
|
public int getLcbPlcffldFtn()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDFTN);
|
|
}
|
|
|
|
@Deprecated
|
|
public void setFcPlcffldFtn( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDFTN, offset );
|
|
}
|
|
|
|
@Deprecated
|
|
public void setLcbPlcffldFtn( int size )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDFTN, size );
|
|
}
|
|
|
|
@Deprecated
|
|
public int getFcPlcffldHdr()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDHDR);
|
|
}
|
|
|
|
@Deprecated
|
|
public int getLcbPlcffldHdr()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDHDR);
|
|
}
|
|
|
|
@Deprecated
|
|
public void setFcPlcffldHdr( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDHDR, offset );
|
|
}
|
|
|
|
@Deprecated
|
|
public void setLcbPlcffldHdr( int size )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDHDR, size );
|
|
}
|
|
|
|
@Deprecated
|
|
public int getFcPlcffldHdrtxbx()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDHDRTXBX);
|
|
}
|
|
|
|
@Deprecated
|
|
public int getLcbPlcffldHdrtxbx()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDHDRTXBX);
|
|
}
|
|
|
|
@Deprecated
|
|
public void setFcPlcffldHdrtxbx( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDHDRTXBX, offset );
|
|
}
|
|
|
|
@Deprecated
|
|
public void setLcbPlcffldHdrtxbx( int size )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDHDRTXBX, size );
|
|
}
|
|
|
|
@Deprecated
|
|
public int getFcPlcffldMom()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDMOM);
|
|
}
|
|
|
|
@Deprecated
|
|
public int getLcbPlcffldMom()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDMOM);
|
|
}
|
|
|
|
@Deprecated
|
|
public void setFcPlcffldMom( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDMOM, offset );
|
|
}
|
|
|
|
@Deprecated
|
|
public void setLcbPlcffldMom( int size )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDMOM, size );
|
|
}
|
|
|
|
@Deprecated
|
|
public int getFcPlcffldTxbx()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDTXBX);
|
|
}
|
|
|
|
@Deprecated
|
|
public int getLcbPlcffldTxbx()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDTXBX);
|
|
}
|
|
|
|
@Deprecated
|
|
public void setFcPlcffldTxbx( int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDTXBX, offset );
|
|
}
|
|
|
|
@Deprecated
|
|
public void setLcbPlcffldTxbx( int size )
|
|
{
|
|
_fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDTXBX, size );
|
|
}
|
|
|
|
|
|
public int getFSPAPlcfOffset( FSPADocumentPart part )
|
|
{
|
|
return _fieldHandler.getFieldOffset( part.getFibFieldsField() );
|
|
}
|
|
|
|
public int getFSPAPlcfLength( FSPADocumentPart part )
|
|
{
|
|
return _fieldHandler.getFieldSize( part.getFibFieldsField() );
|
|
}
|
|
|
|
public void setFSPAPlcfOffset( FSPADocumentPart part, int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( part.getFibFieldsField(), offset );
|
|
}
|
|
|
|
public void setFSPAPlcfLength( FSPADocumentPart part, int length )
|
|
{
|
|
_fieldHandler.setFieldSize( part.getFibFieldsField(), length );
|
|
}
|
|
|
|
@Deprecated
|
|
public int getFcPlcspaMom()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCSPAMOM);
|
|
}
|
|
|
|
@Deprecated
|
|
public int getLcbPlcspaMom()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.PLCSPAMOM);
|
|
}
|
|
|
|
public int getFcDggInfo()
|
|
{
|
|
return _fieldHandler.getFieldOffset(FIBFieldHandler.DGGINFO);
|
|
}
|
|
|
|
public int getLcbDggInfo()
|
|
{
|
|
return _fieldHandler.getFieldSize(FIBFieldHandler.DGGINFO);
|
|
}
|
|
|
|
public int getNotesDescriptorsOffset( NoteType noteType )
|
|
{
|
|
return _fieldHandler.getFieldOffset( noteType
|
|
.getFibDescriptorsFieldIndex() );
|
|
}
|
|
|
|
public void setNotesDescriptorsOffset( NoteType noteType, int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( noteType.getFibDescriptorsFieldIndex(),
|
|
offset );
|
|
}
|
|
|
|
public int getNotesDescriptorsSize( NoteType noteType )
|
|
{
|
|
return _fieldHandler.getFieldSize( noteType
|
|
.getFibDescriptorsFieldIndex() );
|
|
}
|
|
|
|
public void setNotesDescriptorsSize( NoteType noteType, int offset )
|
|
{
|
|
_fieldHandler.setFieldSize( noteType.getFibDescriptorsFieldIndex(),
|
|
offset );
|
|
}
|
|
|
|
public int getNotesTextPositionsOffset( NoteType noteType )
|
|
{
|
|
return _fieldHandler.getFieldOffset( noteType
|
|
.getFibTextPositionsFieldIndex() );
|
|
}
|
|
|
|
public void setNotesTextPositionsOffset( NoteType noteType, int offset )
|
|
{
|
|
_fieldHandler.setFieldOffset( noteType.getFibTextPositionsFieldIndex(),
|
|
offset );
|
|
}
|
|
|
|
public int getNotesTextPositionsSize( NoteType noteType )
|
|
{
|
|
return _fieldHandler.getFieldSize( noteType
|
|
.getFibTextPositionsFieldIndex() );
|
|
}
|
|
|
|
public void setNotesTextPositionsSize( NoteType noteType, int offset )
|
|
{
|
|
_fieldHandler.setFieldSize( noteType.getFibTextPositionsFieldIndex(),
|
|
offset );
|
|
}
|
|
|
|
public void writeTo( byte[] mainStream, HWPFOutputStream tableStream )
|
|
throws IOException
|
|
{
|
|
_cbRgFcLcb = _fieldHandler.getFieldsCount();
|
|
|
|
_fibBase.serialize( mainStream, 0 );
|
|
int offset = FibBase.getSize();
|
|
|
|
LittleEndian.putUShort( mainStream, offset, _csw );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
|
|
_fibRgW.serialize( mainStream, offset );
|
|
offset += FibRgW97.getSize();
|
|
|
|
LittleEndian.putUShort( mainStream, offset, _cslw );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
|
|
( (FibRgLw97) _fibRgLw ).serialize( mainStream, offset );
|
|
offset += FibRgLw97.getSize();
|
|
|
|
LittleEndian.putUShort( mainStream, offset, _cbRgFcLcb );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
|
|
_fieldHandler.writeTo( mainStream, offset, tableStream );
|
|
offset += _cbRgFcLcb * LittleEndian.INT_SIZE * 2;
|
|
|
|
LittleEndian.putUShort( mainStream, offset, _cswNew );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
if ( _cswNew != 0 )
|
|
{
|
|
LittleEndian.putUShort( mainStream, offset, _nFibNew );
|
|
offset += LittleEndian.SHORT_SIZE;
|
|
|
|
System.arraycopy( _fibRgCswNew, 0, mainStream, offset,
|
|
_fibRgCswNew.length );
|
|
offset += _fibRgCswNew.length;
|
|
}
|
|
}
|
|
|
|
public int getSize()
|
|
{
|
|
return FibBase.getSize() + LittleEndian.SHORT_SIZE + FibRgW97.getSize()
|
|
+ LittleEndian.SHORT_SIZE + FibRgLw97.getSize()
|
|
+ LittleEndian.SHORT_SIZE + _fieldHandler.sizeInBytes();
|
|
}
|
|
|
|
public FibBase getFibBase()
|
|
{
|
|
return _fibBase;
|
|
}
|
|
}
|