diff options
author | Fong Lin <pflin@novell.com> | 2010-10-08 17:04:46 +0100 |
---|---|---|
committer | Michael Meeks <michael.meeks@novell.com> | 2010-10-08 17:04:46 +0100 |
commit | cc316b39d9110c536e1758a4f814738ca209bb02 (patch) | |
tree | 0ff290d366ff8fea16ebc7e7781cc14b563f9b37 /lotuswordpro/source/filter/tocread.cxx | |
parent | 949fa63a66adc1ba54a0c353afd66bb863024d27 (diff) |
Port of Lotus Word Pro filter, by Fong Lin and Noel Power
Diffstat (limited to 'lotuswordpro/source/filter/tocread.cxx')
-rw-r--r-- | lotuswordpro/source/filter/tocread.cxx | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/lotuswordpro/source/filter/tocread.cxx b/lotuswordpro/source/filter/tocread.cxx new file mode 100644 index 000000000000..a324a4ed3de1 --- /dev/null +++ b/lotuswordpro/source/filter/tocread.cxx @@ -0,0 +1,516 @@ +/************************************************************************* + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: IBM Corporation + * + * Copyright: 2008 by IBM Corporation + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#include "first.hxx" +#include "assert.h" +namespace OpenStormBento +{ + +BenError +CBenTOCReader::ReadLabelAndTOC() +{ + BenError Err; + + unsigned long TOCOffset; + if ((Err = ReadLabel(&TOCOffset, &cTOCSize)) != BenErr_OK) + return Err; + + if ((Err = cpContainer->SeekToPosition(TOCOffset)) != BenErr_OK) + return Err; + + cpTOC = new BenByte[cTOCSize]; + if ((Err = cpContainer->ReadKnownSize(cpTOC, cTOCSize)) != BenErr_OK) + return Err; + + if ((Err = ReadTOC()) != BenErr_OK) + return Err; + + return BenErr_OK; +} + +BenError +CBenTOCReader::ReadLabel(unsigned long * pTOCOffset, unsigned long * pTOCSize) +{ + // If seek fails, then probably because stream is smaller than + // BEN_LABEL_SIZE and thus can't be Bento container + BenError Err; + if ((Err = cpContainer->SeekFromEnd(-BEN_LABEL_SIZE)) != BenErr_OK) + return BenErr_NotBentoContainer; + + BenByte Label[BEN_LABEL_SIZE]; + if ((Err = cpContainer->ReadKnownSize(Label, BEN_LABEL_SIZE)) != BenErr_OK) + return Err; + + if (memcmp(Label, gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) != 0) + if ((Err = SearchForLabel(Label)) != BenErr_OK) + return Err; + + BenByte * pCurrLabel = Label + BEN_MAGIC_BYTES_SIZE; + + BenWord Flags = UtGetIntelWord(pCurrLabel); pCurrLabel += 2; // Flags + // Newer files are 0x0101--indicates if big or little endian. Older + // files are 0x0 for flags + assert(Flags == 0x0101 || Flags == 0x0); + + cBlockSize = UtGetIntelWord(pCurrLabel) * 1024; pCurrLabel += 2; + + // Check major version + if (UtGetIntelWord(pCurrLabel) != BEN_CURR_MAJOR_VERSION) + return BenErr_UnknownBentoFormatVersion; + pCurrLabel += 2; + + UtGetIntelWord(pCurrLabel); pCurrLabel += 2; // Minor version + + *pTOCOffset = UtGetIntelDWord(pCurrLabel); pCurrLabel += 4; + *pTOCSize = UtGetIntelDWord(pCurrLabel); + + assert(pCurrLabel + 4 == Label + BEN_LABEL_SIZE); + + return BenErr_OK; +} + +#define LABEL_READ_BUFFER_SIZE 500 +#define MAX_SEARCH_AMOUNT 1024 * 1024 + +BenError +CBenTOCReader::SearchForLabel(BenByte * pLabel) +{ + BenError Err; + + unsigned long Length; + if ((Err = cpContainer->GetSize(&Length)) != BenErr_OK) + return Err; + + // Always ready to check for MagicBytes from + // CurrOffset - BEN_MAGIC_BYTES_SIZE to CurrOffset - 1 + unsigned long CurrOffset = Length - BEN_LABEL_SIZE + BEN_MAGIC_BYTES_SIZE - + 1; + + char Buffer[LABEL_READ_BUFFER_SIZE]; + + unsigned long BufferStartOffset = Length; // Init to big value + + while (CurrOffset >= BEN_MAGIC_BYTES_SIZE) + { + // Don't search backwards more than 1 meg + if (Length - CurrOffset > MAX_SEARCH_AMOUNT) + break; + + unsigned long UsedBufferSize; + + // If before beginning of buffer + if (CurrOffset - BEN_MAGIC_BYTES_SIZE < BufferStartOffset) + { + if (CurrOffset < LABEL_READ_BUFFER_SIZE) + UsedBufferSize = CurrOffset; + else UsedBufferSize = LABEL_READ_BUFFER_SIZE; + + if ((Err = cpContainer->SeekToPosition(CurrOffset - UsedBufferSize)) + != BenErr_OK) + return Err; + + if ((Err = cpContainer->ReadKnownSize(Buffer, UsedBufferSize)) != + BenErr_OK) + return Err; + + BufferStartOffset = CurrOffset - UsedBufferSize; + } + + if (memcmp(Buffer + (CurrOffset - BEN_MAGIC_BYTES_SIZE - + BufferStartOffset), gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) == 0) + { + if ((Err = cpContainer->SeekToPosition(CurrOffset - + BEN_MAGIC_BYTES_SIZE)) != BenErr_OK) + return Err; + + return cpContainer->ReadKnownSize(pLabel, BEN_LABEL_SIZE); + } + + --CurrOffset; + } + + return BenErr_NotBentoContainer; // Didn't find magic bytes +} + +BenError +CBenTOCReader::ReadTOC() +{ + BenError Err; + BenByte LookAhead = GetCode(); + BenGeneration Generation = 0; + + // Read in all objects + while (LookAhead == BEN_NEW_OBJECT) + { + BenObjectID ObjectID; + if ((Err = GetDWord(&ObjectID)) != BenErr_OK) + return Err; + pCBenObject pObject = NULL; + + // Read in all properties for object + do + { + BenObjectID PropertyID; + + if ((Err = GetDWord(&PropertyID)) != BenErr_OK) + return Err; + pCBenProperty pProperty = NULL; + + // Read in all values for property + do + { + BenObjectID ReferencedListID = 0; + + BenObjectID TypeID; + if ((Err = GetDWord(&TypeID)) != BenErr_OK) + return Err; + LookAhead = GetCode(); + + if (LookAhead == BEN_EXPLICIT_GEN) + { + if ((Err = GetDWord(&Generation)) != BenErr_OK) + return Err; + LookAhead = GetCode(); + } + + if (LookAhead == BEN_REFERENCE_LIST_ID) + { + // Eat it, unless BENUTIL_SUPPORT turned on + if ((Err = GetDWord(&ReferencedListID)) != BenErr_OK) + return Err; + LookAhead = GetCode(); + } + + if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME || + PropertyID == BEN_PROPID_GLOBAL_TYPE_NAME) + { + // Read property or type name + + if (pObject != NULL || TypeID != BEN_TYPEID_7_BIT_ASCII || + LookAhead != BEN_OFFSET4_LEN4) + return BenErr_NamedObjectError; + + BenContainerPos Pos; + unsigned long Length; + + if ((Err = GetDWord(&Pos)) != BenErr_OK) + return Err; + if ((Err = GetDWord(&Length)) != BenErr_OK) + return Err; + LookAhead = GetCode(); + + if ((Err = cpContainer->SeekToPosition(Pos)) != BenErr_OK) + return Err; + + #define STACK_BUFFER_SIZE 256 + char sStackBuffer[STACK_BUFFER_SIZE]; + char * sAllocBuffer; + char * sBuffer; + if (Length > STACK_BUFFER_SIZE) + { + sBuffer = new char[Length]; + sAllocBuffer = sBuffer; + } + else + { + sBuffer = sStackBuffer; + sAllocBuffer = NULL; + } + + if ((Err = cpContainer->ReadKnownSize(sBuffer, Length)) != + BenErr_OK) + { + delete[] sAllocBuffer; + return Err; + } + + pCBenNamedObjectListElmt pPrevNamedObjectListElmt; + if (FindNamedObject(cpContainer->GetNamedObjects(), + sBuffer, &pPrevNamedObjectListElmt) != NULL) + { + delete[] sAllocBuffer; + return BenErr_DuplicateName; + } + + pCBenObject pPrevObject = (pCBenObject) cpContainer-> + GetObjects()->GetLast(); + + if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME) + pObject = new CBenPropertyName(cpContainer, ObjectID, + pPrevObject, sBuffer, pPrevNamedObjectListElmt); + else pObject = new CBenTypeName(cpContainer, ObjectID, + pPrevObject, sBuffer, pPrevNamedObjectListElmt); + + delete[] sAllocBuffer; + } + // If BENUTIL_SUPPORT turned on, read in references object + // like regular object +#ifndef BENUTIL_SUPPORT + else if (PropertyID == BEN_PROPID_OBJ_REFERENCES) + { + // Don't need to read in references object--we assume + // that all references use object ID as key + if ((Err = ReadSegments(NULL, &LookAhead)) != BenErr_OK) + return Err; + } +#endif + else if (ObjectID == BEN_OBJID_TOC) + { + if (PropertyID == BEN_PROPID_TOC_SEED) + { + if (TypeID != BEN_TYPEID_TOC_TYPE || + LookAhead != BEN_IMMEDIATE4) + return BenErr_TOCSeedError; + + BenDWord Data; + if ((Err = GetDWord(&Data)) != BenErr_OK) + return Err; + LookAhead = GetCode(); + + cpContainer->SetNextAvailObjectID(Data); + } + else + { + // Ignore the other BEN_OBJID_TOC properties + if ((Err = ReadSegments(NULL, &LookAhead)) != BenErr_OK) + return Err; + } + } + else + { + if (pProperty != NULL) + return BenErr_PropertyWithMoreThanOneValue; + + if (pObject == NULL) + pObject = new CBenObject(cpContainer, ObjectID, + (pCBenObject) cpContainer->GetObjects()->GetLast()); + + pProperty = new CBenProperty(pObject, PropertyID, TypeID, + (pCBenProperty) pObject->GetProperties()->GetLast()); + +#ifdef BENUTIL_SUPPORT + pProperty->UseValue()-> + SetReferencedListObjectID(ReferencedListID); +#endif + + if ((Err = ReadSegments(pProperty->UseValue(), + &LookAhead)) != BenErr_OK) + return Err; + } + } while (LookAhead == BEN_NEW_TYPE); + } while (LookAhead == BEN_NEW_PROPERTY); + } + + if (LookAhead == BEN_READ_PAST_END_OF_TOC) + return BenErr_OK; + else return BenErr_InvalidTOC; +} + +BenError +CBenTOCReader::ReadSegments(pCBenValue pValue, BenByte * pLookAhead) +{ + BenError Err; + + while (*pLookAhead >= BEN_SEGMENT_CODE_START && + *pLookAhead <= BEN_SEGMENT_CODE_END) + { + if ((Err = ReadSegment(pValue, pLookAhead)) != + BenErr_OK) + return Err; + } + + return BenErr_OK; +} + +BenError +CBenTOCReader::ReadSegment(pCBenValue pValue, BenByte * pLookAhead) +{ + BenError Err; + + UtBool Immediate = UT_FALSE; + UtBool EightByteOffset = UT_FALSE; + unsigned long Offset, Length; + + switch (*pLookAhead) + { + case BEN_CONT_OFFSET4_LEN4: + case BEN_OFFSET4_LEN4: + if ((Err = GetDWord(&Offset)) != BenErr_OK) + return Err; + if ((Err = GetDWord(&Length)) != BenErr_OK) + return Err; + break; + + case BEN_IMMEDIATE0: + Length = 0; Immediate = UT_TRUE; + break; + + case BEN_IMMEDIATE1: + Length = 1; Immediate = UT_TRUE; + break; + + case BEN_IMMEDIATE2: + Length = 2; Immediate = UT_TRUE; + break; + + case BEN_IMMEDIATE3: + Length = 3; Immediate = UT_TRUE; + break; + + case BEN_CONT_IMMEDIATE4: + case BEN_IMMEDIATE4: + Length = 4; Immediate = UT_TRUE; + break; + + case BEN_CONT_OFFSET8_LEN4: + case BEN_OFFSET8_LEN4: + EightByteOffset = UT_TRUE; + break; + + default: + return BenErr_OK; + } + + BenByte ImmData[4]; + if (Immediate && Length != 0) + if ((Err = GetData(ImmData, 4)) != BenErr_OK) + return Err; + + *pLookAhead = GetCode(); + + if (EightByteOffset) + return BenErr_64BitOffsetNotSupported; + + if (pValue != NULL) + { + if (! Immediate) + new CBenValueSegment(pValue, Offset, Length); + else if (Length != 0) + { + assert(Length <= 4); + new CBenValueSegment(pValue, ImmData, (unsigned short) Length); + } + } + + return BenErr_OK; +} + +UtBool +CBenTOCReader::CanGetData(unsigned long Amt) +{ + return cCurr + Amt <= cTOCSize; +} + +BenError +CBenTOCReader::GetByte(BenByte * pByte) +{ + if (! CanGetData(1)) + return BenErr_ReadPastEndOfTOC; + + *pByte = UtGetIntelByte(cpTOC + cCurr); + ++cCurr; + return BenErr_OK; +} + +BenError +CBenTOCReader::GetWord(BenWord * pWord) +{ + if (! CanGetData(2)) + return BenErr_ReadPastEndOfTOC; + + *pWord = UtGetIntelWord(cpTOC + cCurr); + cCurr += 2; + return BenErr_OK; +} + +BenError +CBenTOCReader::GetDWord(BenDWord * pDWord) +{ + if (! CanGetData(4)) + return BenErr_ReadPastEndOfTOC; + + *pDWord = UtGetIntelDWord(cpTOC + cCurr); + cCurr += 4; + return BenErr_OK; +} + +BenByte +CBenTOCReader::GetCode() +{ + BenByte Code; + do + { + if (GetByte(&Code) != BenErr_OK) + return BEN_READ_PAST_END_OF_TOC; + + if (Code == BEN_END_OF_BUFFER) + // Advance to next block + cCurr = cBlockSize * ((cCurr + (cBlockSize - 1)) / + cBlockSize); + } + while (Code == BEN_NOOP || Code == BEN_END_OF_BUFFER); + return Code; +} + +BenError +CBenTOCReader::GetData(BenDataPtr pBuffer, unsigned long Amt) +{ + if (! CanGetData(Amt)) + return BenErr_ReadPastEndOfTOC; + + UtHugeMemcpy(pBuffer, cpTOC + cCurr, Amt); + cCurr += Amt; + return BenErr_OK; +} +}//end OpenStormBento namespace |