fix issues related to document properties loading and saving

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1156662 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sergey Vladimirov 2011-08-11 16:37:31 +00:00
parent f7b888743f
commit 7f72be652e
9 changed files with 1217 additions and 862 deletions

View File

@ -264,7 +264,7 @@ public final class HWPFDocument extends HWPFDocumentCore
//fcMin = _fib.getFcMin() //fcMin = _fib.getFcMin()
// Start to load up our standard structures. // Start to load up our standard structures.
_dop = new DocumentProperties(_tableStream, _fib.getFcDop()); _dop = new DocumentProperties(_tableStream, _fib.getFcDop(), _fib.getLcbDop() );
_cft = new ComplexFileTable(_mainStream, _tableStream, _fib.getFcClx(), fcMin); _cft = new ComplexFileTable(_mainStream, _tableStream, _fib.getFcClx(), fcMin);
TextPieceTable _tpt = _cft.getTextPieceTable(); TextPieceTable _tpt = _cft.getTextPieceTable();
@ -682,6 +682,21 @@ public final class HWPFDocument extends HWPFDocumentCore
tableOffset = tableStream.getOffset(); tableOffset = tableStream.getOffset();
int fcMac = mainStream.getOffset(); int fcMac = mainStream.getOffset();
/*
* dop (document properties record) Written immediately after the end of
* the previously recorded structure. This is recorded in all Word
* documents
*
* Microsoft Office Word 97-2007 Binary File Format (.doc)
* Specification; Page 23 of 210
*/
// write out the DocumentProperties.
_fib.setFcDop(tableOffset);
_dop.writeTo(tableStream);
_fib.setLcbDop(tableStream.getOffset() - tableOffset);
tableOffset = tableStream.getOffset();
/* /*
* plcfBkmkf (table recording beginning CPs of bookmarks) Written * plcfBkmkf (table recording beginning CPs of bookmarks) Written
* immediately after the sttbfBkmk, if the document contains bookmarks. * immediately after the sttbfBkmk, if the document contains bookmarks.
@ -881,13 +896,6 @@ public final class HWPFDocument extends HWPFDocumentCore
_fib.setLcbSttbfffn(tableStream.getOffset() - tableOffset); _fib.setLcbSttbfffn(tableStream.getOffset() - tableOffset);
tableOffset = tableStream.getOffset(); tableOffset = tableStream.getOffset();
// write out the DocumentProperties.
_fib.setFcDop(tableOffset);
byte[] buf = new byte[_dop.getSize()];
_fib.setLcbDop(_dop.getSize());
_dop.serialize(buf, 0);
tableStream.write(buf);
// set some variables in the FileInformationBlock. // set some variables in the FileInformationBlock.
_fib.setFcMin(fcMin); _fib.setFcMin(fcMin);
_fib.setFcMac(fcMac); _fib.setFcMac(fcMac);

View File

@ -101,7 +101,7 @@ public final class HWPFLister
if ( args.length == 0 ) if ( args.length == 0 )
{ {
System.err.println( "Use:" ); System.err.println( "Use:" );
System.err.println( "\tHWPFLister <filename>\n" System.err.println( "\tHWPFLister <filename>\n" + "\t\t[--dop]\n"
+ "\t\t[--textPieces] [--textPiecesText]\n" + "\t\t[--textPieces] [--textPiecesText]\n"
+ "\t\t[--chpx] [--chpxProperties] [--chpxSprms]\n" + "\t\t[--chpx] [--chpxProperties] [--chpxSprms]\n"
+ "\t\t[--papx] [--papxProperties] [--papxSprms]\n" + "\t\t[--papx] [--papxProperties] [--papxSprms]\n"
@ -112,6 +112,8 @@ public final class HWPFLister
System.exit( 1 ); System.exit( 1 );
} }
boolean outputDop = false;
boolean outputTextPieces = false; boolean outputTextPieces = false;
boolean outputTextPiecesText = false; boolean outputTextPiecesText = false;
@ -136,6 +138,9 @@ public final class HWPFLister
for ( String arg : Arrays.asList( args ).subList( 1, args.length ) ) for ( String arg : Arrays.asList( args ).subList( 1, args.length ) )
{ {
if ( "--dop".equals( arg ) )
outputDop = true;
if ( "--textPieces".equals( arg ) ) if ( "--textPieces".equals( arg ) )
outputTextPieces = true; outputTextPieces = true;
if ( "--textPiecesText".equals( arg ) ) if ( "--textPiecesText".equals( arg ) )
@ -197,6 +202,12 @@ public final class HWPFLister
System.out.println( "== FIB (original) ==" ); System.out.println( "== FIB (original) ==" );
listerOriginal.dumpFIB(); listerOriginal.dumpFIB();
if ( outputDop )
{
System.out.println( "== Document properties ==" );
listerOriginal.dumpDop();
}
if ( outputTextPieces ) if ( outputTextPieces )
{ {
System.out.println( "== Text pieces (original) ==" ); System.out.println( "== Text pieces (original) ==" );
@ -371,6 +382,17 @@ public final class HWPFLister
} }
} }
private void dumpDop()
{
if ( !( _doc instanceof HWPFDocument ) )
{
System.out.println( "Word 95 not supported so far" );
return;
}
System.out.println( ( (HWPFDocument) _doc ).getDocProperties() );
}
private void dumpEscher() private void dumpEscher()
{ {
if ( _doc instanceof HWPFOldDocument ) if ( _doc instanceof HWPFOldDocument )

View File

@ -17,19 +17,60 @@
package org.apache.poi.hwpf.model; package org.apache.poi.hwpf.model;
import java.io.IOException;
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
import org.apache.poi.hwpf.model.types.DOPAbstractType; import org.apache.poi.hwpf.model.types.DOPAbstractType;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
/** /**
* Comment me * Comment me
* *
* @author Ryan Ackley * @author Ryan Ackley
*/ */
@Internal @Internal
public final class DocumentProperties extends DOPAbstractType { public final class DocumentProperties extends DOPAbstractType
{
private byte[] _preserved;
public DocumentProperties(byte[] tableStream, int offset) { /**
super.fillFields(tableStream, offset); * @deprecated Use {@link #DocumentProperties(byte[],int,int)} instead
} */
public DocumentProperties( byte[] tableStream, int offset )
{
this( tableStream, offset, DOPAbstractType.getSize() );
}
public DocumentProperties( byte[] tableStream, int offset, int length )
{
super.fillFields( tableStream, offset );
final int supportedSize = DOPAbstractType.getSize();
if ( length != supportedSize )
{
this._preserved = LittleEndian.getByteArray( tableStream, offset
+ supportedSize, length - supportedSize );
}
else
{
_preserved = new byte[0];
}
}
@Override
public void serialize( byte[] data, int offset )
{
super.serialize( data, offset );
}
public void writeTo( HWPFOutputStream tableStream ) throws IOException
{
byte[] supported = new byte[getSize()];
serialize( supported, 0 );
tableStream.write( supported );
tableStream.write( _preserved );
}
} }

View File

@ -71,6 +71,7 @@ public final class FIBFieldHandler
public static final int PRENVPORT = 28; public static final int PRENVPORT = 28;
public static final int PRENVLAND = 29; public static final int PRENVLAND = 29;
public static final int WSS = 30; public static final int WSS = 30;
// 402 == 0x0192; 406 == 0x0196
public static final int DOP = 31; public static final int DOP = 31;
public static final int STTBFASSOC = 32; public static final int STTBFASSOC = 32;
public static final int CLX = 33; public static final int CLX = 33;

View File

@ -135,7 +135,11 @@ public class FieldsTables
throws IOException throws IOException
{ {
if ( plexOfCps == null || plexOfCps.length() == 0 ) if ( plexOfCps == null || plexOfCps.length() == 0 )
{
fib.setFieldsPlcfOffset( part, outputStream.getOffset() );
fib.setFieldsPlcfLength( part, 0 );
return 0; return 0;
}
byte[] data = plexOfCps.toByteArray(); byte[] data = plexOfCps.toByteArray();

View File

@ -87,7 +87,7 @@ public class NotesTables
{ {
if ( descriptors == null || descriptors.length() == 0 ) if ( descriptors == null || descriptors.length() == 0 )
{ {
fib.setNotesDescriptorsOffset( noteType, 0 ); fib.setNotesDescriptorsOffset( noteType, tableStream.getOffset() );
fib.setNotesDescriptorsSize( noteType, 0 ); fib.setNotesDescriptorsSize( noteType, 0 );
return; return;
} }
@ -105,7 +105,7 @@ public class NotesTables
{ {
if ( textPositions == null || textPositions.length() == 0 ) if ( textPositions == null || textPositions.length() == 0 )
{ {
fib.setNotesTextPositionsOffset( noteType, 0 ); fib.setNotesTextPositionsOffset( noteType, tableStream.getOffset() );
fib.setNotesTextPositionsSize( noteType, 0 ); fib.setNotesTextPositionsSize( noteType, 0 );
return; return;
} }

View File

@ -39,7 +39,7 @@ public final class TestDocumentProperties
_documentProperties.serialize(buf, 0); _documentProperties.serialize(buf, 0);
DocumentProperties newDocProperties = DocumentProperties newDocProperties =
new DocumentProperties(buf, 0); new DocumentProperties(buf, 0, size);
Field[] fields = DocumentProperties.class.getSuperclass().getDeclaredFields(); Field[] fields = DocumentProperties.class.getSuperclass().getDeclaredFields();
AccessibleObject.setAccessible(fields, true); AccessibleObject.setAccessible(fields, true);
@ -71,7 +71,7 @@ public final class TestDocumentProperties
_hWPFDocFixture.setUp(); _hWPFDocFixture.setUp();
_documentProperties = new DocumentProperties(_hWPFDocFixture._tableStream, _hWPFDocFixture._fib.getFcDop()); _documentProperties = new DocumentProperties(_hWPFDocFixture._tableStream, _hWPFDocFixture._fib.getFcDop(), _hWPFDocFixture._fib.getLcbDop());
} }
protected void tearDown() protected void tearDown()

View File

@ -16,21 +16,15 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.hwpf.usermodel; package org.apache.poi.hwpf.usermodel;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.apache.poi.util.LittleEndian;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hwpf.model.SubdocumentType;
import org.apache.poi.hwpf.model.FileInformationBlock;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.poi.POIDataSamples; import org.apache.poi.POIDataSamples;
import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFDocument;
@ -39,8 +33,12 @@ import org.apache.poi.hwpf.HWPFTestDataSamples;
import org.apache.poi.hwpf.extractor.Word6Extractor; import org.apache.poi.hwpf.extractor.Word6Extractor;
import org.apache.poi.hwpf.extractor.WordExtractor; import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.hwpf.model.FieldsDocumentPart; import org.apache.poi.hwpf.model.FieldsDocumentPart;
import org.apache.poi.hwpf.model.FileInformationBlock;
import org.apache.poi.hwpf.model.PlexOfField; import org.apache.poi.hwpf.model.PlexOfField;
import org.apache.poi.hwpf.model.SubdocumentType;
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
/** /**
* Test different problems reported in Apache Bugzilla * Test different problems reported in Apache Bugzilla
@ -549,11 +547,13 @@ public class TestBugs extends TestCase
/** /**
* [RESOLVED FIXED] Bug 51604 - replace text fails for doc ( poi 3.8 beta * [RESOLVED FIXED] Bug 51604 - replace text fails for doc ( poi 3.8 beta
* release from download site ) * release from download site )
*
* @throws IOException
* @throws FileNotFoundException
*/ */
public void test51604p2() public void test51604p2() throws FileNotFoundException, IOException
{ {
HWPFDocument doc = HWPFTestDataSamples HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "Bug51604.doc" );
.openSampleFile( "Bug51604.doc" );
Range range = doc.getRange(); Range range = doc.getRange();
int numParagraph = range.numParagraphs(); int numParagraph = range.numParagraphs();
@ -583,7 +583,49 @@ public class TestBugs extends TestCase
totalLength += partLength; totalLength += partLength;
} }
}
assertEquals( doc.getText().length(), totalLength ); /**
* [RESOLVED FIXED] Bug 51604 - replace text fails for doc ( poi 3.8 beta
* release from download site )
*/
public void test51604p3() throws IOException
{
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "Bug51604.doc" );
byte[] originalData = new byte[doc.getFileInformationBlock()
.getLcbDop()];
System.arraycopy( doc.getTableStream(), doc.getFileInformationBlock()
.getFcDop(), originalData, 0, originalData.length );
HWPFOutputStream outputStream = new HWPFOutputStream();
doc.getDocProperties().writeTo( outputStream );
final byte[] oldData = outputStream.toByteArray();
assertEquals( Arrays.toString( originalData ),
Arrays.toString( oldData ) );
Range range = doc.getRange();
int numParagraph = range.numParagraphs();
for ( int i = 0; i < numParagraph; i++ )
{
Paragraph paragraph = range.getParagraph( i );
int numCharRuns = paragraph.numCharacterRuns();
for ( int j = 0; j < numCharRuns; j++ )
{
CharacterRun charRun = paragraph.getCharacterRun( j );
String text = charRun.text();
if ( text.contains( "Header" ) )
charRun.replaceText( text, "added" );
}
}
doc = HWPFTestDataSamples.writeOutAndReadBack( doc );
outputStream = new HWPFOutputStream();
doc.getDocProperties().writeTo( outputStream );
final byte[] newData = outputStream.toByteArray();
assertEquals( Arrays.toString( oldData ), Arrays.toString( newData ) );
} }
} }