/* ==================================================================== 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; import java.io.IOException; import java.io.OutputStream; import org.apache.poi.hwpf.model.ComplexFileTable; import org.apache.poi.hwpf.model.OldCHPBinTable; import org.apache.poi.hwpf.model.OldPAPBinTable; import org.apache.poi.hwpf.model.OldSectionTable; import org.apache.poi.hwpf.model.PieceDescriptor; import org.apache.poi.hwpf.model.TextPiece; import org.apache.poi.hwpf.model.TextPieceTable; import org.apache.poi.hwpf.usermodel.Range; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.LittleEndian; /** * Provides very simple support for old (Word 6 / Word 95) * files. */ public class HWPFOldDocument extends HWPFDocumentCore { private TextPieceTable tpt; private StringBuilder _text; public HWPFOldDocument(POIFSFileSystem fs) throws IOException { this(fs.getRoot()); } @Deprecated public HWPFOldDocument(DirectoryNode directory, POIFSFileSystem fs) throws IOException { this(directory); } public HWPFOldDocument(DirectoryNode directory) throws IOException { super(directory); // Where are things? int sedTableOffset = LittleEndian.getInt(_mainStream, 0x88); int sedTableSize = LittleEndian.getInt(_mainStream, 0x8c); int chpTableOffset = LittleEndian.getInt(_mainStream, 0xb8); int chpTableSize = LittleEndian.getInt(_mainStream, 0xbc); int papTableOffset = LittleEndian.getInt(_mainStream, 0xc0); int papTableSize = LittleEndian.getInt(_mainStream, 0xc4); //int shfTableOffset = LittleEndian.getInt(_mainStream, 0x60); //int shfTableSize = LittleEndian.getInt(_mainStream, 0x64); int complexTableOffset = LittleEndian.getInt(_mainStream, 0x160); // We need to get hold of the text that makes up the // document, which might be regular or fast-saved ComplexFileTable cft = null; StringBuffer text = new StringBuffer(); if(_fib.getFibBase().isFComplex()) { cft = new ComplexFileTable( _mainStream, _mainStream, complexTableOffset, _fib.getFibBase().getFcMin() ); tpt = cft.getTextPieceTable(); for(TextPiece tp : tpt.getTextPieces()) { text.append( tp.getStringBuilder() ); } } else { // TODO Discover if these older documents can ever hold Unicode Strings? // (We think not, because they seem to lack a Piece table) // TODO Build the Piece Descriptor properly // (We have to fake it, as they don't seem to have a proper Piece table) PieceDescriptor pd = new PieceDescriptor(new byte[] {0,0, 0,0,0,127, 0,0}, 0); pd.setFilePosition(_fib.getFibBase().getFcMin()); // Generate a single Text Piece Table, with a single Text Piece // which covers all the (8 bit only) text in the file tpt = new TextPieceTable(); byte[] textData = new byte[_fib.getFibBase().getFcMac()-_fib.getFibBase().getFcMin()]; System.arraycopy(_mainStream, _fib.getFibBase().getFcMin(), textData, 0, textData.length); TextPiece tp = new TextPiece( 0, textData.length, textData, pd ); tpt.add(tp); text.append(tp.getStringBuilder()); } _text = tpt.getText(); // Now we can fetch the character and paragraph properties _cbt = new OldCHPBinTable( _mainStream, chpTableOffset, chpTableSize, _fib.getFibBase().getFcMin(), tpt ); _pbt = new OldPAPBinTable( _mainStream, papTableOffset, papTableSize, _fib.getFibBase().getFcMin(), tpt ); _st = new OldSectionTable( _mainStream, sedTableOffset, sedTableSize, _fib.getFibBase().getFcMin(), tpt ); /* * in this mode we preserving PAPX/CHPX structure from file, so text may * miss from output, and text order may be corrupted */ boolean preserveBinTables = false; try { preserveBinTables = Boolean.parseBoolean( System .getProperty( HWPFDocument.PROPERTY_PRESERVE_BIN_TABLES ) ); } catch ( Exception exc ) { // ignore; } if ( !preserveBinTables ) { _cbt.rebuild( cft ); _pbt.rebuild( _text, cft ); } } public Range getOverallRange() { // Life is easy when we have no footers, headers or unicode! return new Range( 0, _fib.getFibBase().getFcMac() - _fib.getFibBase().getFcMin(), this ); } public Range getRange() { return getOverallRange(); } public TextPieceTable getTextTable() { return tpt; } @Override public StringBuilder getText() { return _text; } @Override public void write(OutputStream out) throws IOException { throw new IllegalStateException("Writing is not available for the older file formats"); } }