bump product version to 6.1.0.2
[LibreOffice.git] / lotuswordpro / source / filter / tocread.cxx
blobe6af6f42e8f129b769981b4e1edeac7559f5b2a0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * The Contents of this file are made available subject to the terms of
5 * either of the following licenses
7 * - GNU Lesser General Public License Version 2.1
8 * - Sun Industry Standards Source License Version 1.1
10 * Sun Microsystems Inc., October, 2000
12 * GNU Lesser General Public License Version 2.1
13 * =============================================
14 * Copyright 2000 by Sun Microsystems, Inc.
15 * 901 San Antonio Road, Palo Alto, CA 94303, USA
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License version 2.1, as published by the Free Software Foundation.
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 * MA 02111-1307 USA
32 * Sun Industry Standards Source License Version 1.1
33 * =================================================
34 * The contents of this file are subject to the Sun Industry Standards
35 * Source License Version 1.1 (the "License"); You may not use this file
36 * except in compliance with the License. You may obtain a copy of the
37 * License at http://www.openoffice.org/license.html.
39 * Software provided under this License is provided on an "AS IS" basis,
40 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43 * See the License for the specific provisions governing your rights and
44 * obligations concerning the Software.
46 * The Initial Developer of the Original Code is: IBM Corporation
48 * Copyright: 2008 by IBM Corporation
50 * All Rights Reserved.
52 * Contributor(s): _______________________________________
55 ************************************************************************/
57 #include <sal/config.h>
59 #include <cstring>
61 #include "first.hxx"
62 #include <assert.h>
63 namespace OpenStormBento
66 BenError
67 CBenTOCReader::ReadLabelAndTOC()
69 BenError Err;
71 unsigned long TOCOffset;
72 if ((Err = ReadLabel(&TOCOffset, &cTOCSize)) != BenErr_OK)
73 return Err;
75 sal_uLong nLength = cpContainer->GetSize();
77 if (TOCOffset > nLength)
78 return BenErr_ReadPastEndOfTOC;
80 if (cTOCSize > nLength - TOCOffset)
81 return BenErr_ReadPastEndOfTOC;
83 if ((Err = cpContainer->SeekToPosition(TOCOffset)) != BenErr_OK)
84 return Err;
86 cpTOC.reset( new BenByte[cTOCSize] );
87 if ((Err = cpContainer->ReadKnownSize(cpTOC.get(), cTOCSize)) != BenErr_OK)
88 return Err;
90 if ((Err = ReadTOC()) != BenErr_OK)
91 return Err;
93 return BenErr_OK;
96 BenError
97 CBenTOCReader::ReadLabel(unsigned long * pTOCOffset, unsigned long * pTOCSize)
99 // If seek fails, then probably because stream is smaller than
100 // BEN_LABEL_SIZE and thus can't be Bento container
101 BenError Err;
102 if ((Err = cpContainer->SeekFromEnd(-BEN_LABEL_SIZE)) != BenErr_OK)
103 return BenErr_NotBentoContainer;
105 BenByte Label[BEN_LABEL_SIZE];
106 if ((Err = cpContainer->ReadKnownSize(Label, BEN_LABEL_SIZE)) != BenErr_OK)
107 return Err;
109 if (memcmp(Label, gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) != 0)
110 if ((Err = SearchForLabel(Label)) != BenErr_OK)
111 return Err;
113 BenByte * pCurrLabel = Label + BEN_MAGIC_BYTES_SIZE;
115 BenWord Flags =
116 UtGetIntelWord(pCurrLabel); pCurrLabel += 2; // Flags
117 // Newer files are 0x0101--indicates if big or little endian. Older
118 // files are 0x0 for flags
119 if (Flags != 0x0101 && Flags != 0x0)
120 return BenErr_UnknownBentoFormatVersion;
122 cBlockSize = UtGetIntelWord(pCurrLabel) * 1024; pCurrLabel += 2;
123 if (cBlockSize == 0)
124 return BenErr_NotBentoContainer;
126 // Check major version
127 if (UtGetIntelWord(pCurrLabel) != BEN_CURR_MAJOR_VERSION)
128 return BenErr_UnknownBentoFormatVersion;
129 pCurrLabel += 2;
131 pCurrLabel += 2; // Minor version
133 *pTOCOffset = UtGetIntelDWord(pCurrLabel); pCurrLabel += 4;
134 *pTOCSize = UtGetIntelDWord(pCurrLabel);
136 assert(pCurrLabel + 4 == Label + BEN_LABEL_SIZE);
138 return BenErr_OK;
141 #define LABEL_READ_BUFFER_SIZE 500
142 #define MAX_SEARCH_AMOUNT 1024 * 1024
144 BenError
145 CBenTOCReader::SearchForLabel(BenByte * pLabel)
147 BenError Err;
149 sal_uLong Length = cpContainer->GetSize();
151 // Always ready to check for MagicBytes from
152 // CurrOffset - BEN_MAGIC_BYTES_SIZE to CurrOffset - 1
153 unsigned long CurrOffset = Length - BEN_LABEL_SIZE + BEN_MAGIC_BYTES_SIZE -
156 char Buffer[LABEL_READ_BUFFER_SIZE] = {0};
158 unsigned long BufferStartOffset = Length; // Init to big value
160 while (CurrOffset >= BEN_MAGIC_BYTES_SIZE)
162 // Don't search backwards more than 1 meg
163 if (Length - CurrOffset > MAX_SEARCH_AMOUNT)
164 break;
166 // If before beginning of buffer
167 if (CurrOffset - BEN_MAGIC_BYTES_SIZE < BufferStartOffset)
169 unsigned long UsedBufferSize;
170 if (CurrOffset < LABEL_READ_BUFFER_SIZE)
171 UsedBufferSize = CurrOffset;
172 else UsedBufferSize = LABEL_READ_BUFFER_SIZE;
174 if ((Err = cpContainer->SeekToPosition(CurrOffset - UsedBufferSize))
175 != BenErr_OK)
176 return Err;
178 if ((Err = cpContainer->ReadKnownSize(Buffer, UsedBufferSize)) !=
179 BenErr_OK)
180 return Err;
182 BufferStartOffset = CurrOffset - UsedBufferSize;
185 if (memcmp(Buffer + (CurrOffset - BEN_MAGIC_BYTES_SIZE -
186 BufferStartOffset), gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) == 0)
188 if ((Err = cpContainer->SeekToPosition(CurrOffset -
189 BEN_MAGIC_BYTES_SIZE)) != BenErr_OK)
190 return Err;
192 return cpContainer->ReadKnownSize(pLabel, BEN_LABEL_SIZE);
195 --CurrOffset;
198 return BenErr_NotBentoContainer; // Didn't find magic bytes
201 BenError
202 CBenTOCReader::ReadTOC()
204 BenError Err;
205 BenByte LookAhead = GetCode();
206 BenGeneration Generation = 0;
208 // Read in all objects
209 while (LookAhead == BEN_NEW_OBJECT)
211 BenObjectID ObjectID;
212 if ((Err = GetDWord(&ObjectID)) != BenErr_OK)
213 return Err;
214 CBenObject * pObject = nullptr;
216 // Read in all properties for object
219 BenObjectID PropertyID;
221 if ((Err = GetDWord(&PropertyID)) != BenErr_OK)
222 return Err;
223 CBenProperty * pProperty = nullptr;
225 // Read in all values for property
228 BenObjectID ReferencedListID = 0;
230 BenObjectID TypeID;
231 if ((Err = GetDWord(&TypeID)) != BenErr_OK)
232 return Err;
233 LookAhead = GetCode();
235 if (LookAhead == BEN_EXPLICIT_GEN)
237 if ((Err = GetDWord(&Generation)) != BenErr_OK)
238 return Err;
239 LookAhead = GetCode();
242 if (LookAhead == BEN_REFERENCE_LIST_ID)
244 if ((Err = GetDWord(&ReferencedListID)) != BenErr_OK)
245 return Err;
246 LookAhead = GetCode();
249 if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME ||
250 PropertyID == BEN_PROPID_GLOBAL_TYPE_NAME)
252 // Read property or type name
254 if (pObject != nullptr || TypeID != BEN_TYPEID_7_BIT_ASCII ||
255 LookAhead != BEN_OFFSET4_LEN4)
256 return BenErr_NamedObjectError;
258 BenContainerPos Pos;
259 sal_uInt32 Length;
261 if ((Err = GetDWord(&Pos)) != BenErr_OK)
262 return Err;
263 if ((Err = GetDWord(&Length)) != BenErr_OK)
264 return Err;
265 LookAhead = GetCode();
267 if ((Err = cpContainer->SeekToPosition(Pos)) != BenErr_OK)
268 return Err;
270 const auto nRemainingSize = cpContainer->remainingSize();
271 if (Length > nRemainingSize)
273 SAL_WARN("lwp", "stream too short for claimed no of records");
274 Length = nRemainingSize;
277 #define STACK_BUFFER_SIZE 256
278 char sStackBuffer[STACK_BUFFER_SIZE];
279 char * sAllocBuffer;
280 char * sBuffer;
281 if (Length > STACK_BUFFER_SIZE)
283 sBuffer = new char[Length];
284 sAllocBuffer = sBuffer;
286 else
288 sBuffer = sStackBuffer;
289 sAllocBuffer = nullptr;
292 if ((Err = cpContainer->ReadKnownSize(sBuffer, Length)) !=
293 BenErr_OK)
295 delete[] sAllocBuffer;
296 return Err;
299 OString sName(sBuffer, Length);
301 CUtListElmt * pPrevNamedObjectListElmt;
302 if (FindNamedObject(&cpContainer->GetNamedObjects(),
303 sName, &pPrevNamedObjectListElmt) != nullptr)
305 delete[] sAllocBuffer;
306 return BenErr_DuplicateName;
309 CUtListElmt* pPrevObject = cpContainer->GetObjects().GetLast();
311 if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME)
312 pObject = new CBenPropertyName(cpContainer, ObjectID,
313 pPrevObject, sName, pPrevNamedObjectListElmt);
314 else pObject = new CBenTypeName(cpContainer, ObjectID,
315 pPrevObject, sName, pPrevNamedObjectListElmt);
317 delete[] sAllocBuffer;
319 else if (PropertyID == BEN_PROPID_OBJ_REFERENCES)
321 // Don't need to read in references object--we assume
322 // that all references use object ID as key
323 if ((Err = ReadSegments(nullptr, &LookAhead)) != BenErr_OK)
324 return Err;
326 else if (ObjectID == BEN_OBJID_TOC)
328 if (PropertyID == BEN_PROPID_TOC_SEED)
330 if (TypeID != BEN_TYPEID_TOC_TYPE ||
331 LookAhead != BEN_IMMEDIATE4)
332 return BenErr_TOCSeedError;
334 BenDWord Data;
335 if ((Err = GetDWord(&Data)) != BenErr_OK)
336 return Err;
337 LookAhead = GetCode();
339 cpContainer->SetNextAvailObjectID(Data);
341 else
343 // Ignore the other BEN_OBJID_TOC properties
344 if ((Err = ReadSegments(nullptr, &LookAhead)) != BenErr_OK)
345 return Err;
348 else
350 if (pProperty != nullptr)
351 return BenErr_PropertyWithMoreThanOneValue;
353 if (pObject == nullptr)
354 pObject = new CBenObject(cpContainer, ObjectID,
355 cpContainer->GetObjects().GetLast());
357 pProperty = new CBenProperty(pObject, PropertyID, TypeID,
358 pObject->GetProperties().GetLast());
360 if ((Err = ReadSegments(&pProperty->UseValue(),
361 &LookAhead)) != BenErr_OK)
362 return Err;
364 } while (LookAhead == BEN_NEW_TYPE);
365 } while (LookAhead == BEN_NEW_PROPERTY);
368 if (LookAhead == BEN_READ_PAST_END_OF_TOC)
369 return BenErr_OK;
370 else return BenErr_InvalidTOC;
373 BenError
374 CBenTOCReader::ReadSegments(CBenValue * pValue, BenByte * pLookAhead)
376 BenError Err;
378 while (*pLookAhead >= BEN_SEGMENT_CODE_START &&
379 *pLookAhead <= BEN_SEGMENT_CODE_END)
381 if ((Err = ReadSegment(pValue, pLookAhead)) !=
382 BenErr_OK)
383 return Err;
386 return BenErr_OK;
389 BenError
390 CBenTOCReader::ReadSegment(CBenValue * pValue, BenByte * pLookAhead)
392 BenError Err;
394 bool Immediate = false;
395 bool EightByteOffset = false;
396 sal_uInt32 Offset(0), Length(0);
398 switch (*pLookAhead)
400 case BEN_CONT_OFFSET4_LEN4:
401 case BEN_OFFSET4_LEN4:
402 if ((Err = GetDWord(&Offset)) != BenErr_OK)
403 return Err;
404 if ((Err = GetDWord(&Length)) != BenErr_OK)
405 return Err;
406 break;
408 case BEN_IMMEDIATE0:
409 Length = 0; Immediate = true;
410 break;
412 case BEN_IMMEDIATE1:
413 Length = 1; Immediate = true;
414 break;
416 case BEN_IMMEDIATE2:
417 Length = 2; Immediate = true;
418 break;
420 case BEN_IMMEDIATE3:
421 Length = 3; Immediate = true;
422 break;
424 case BEN_CONT_IMMEDIATE4:
425 case BEN_IMMEDIATE4:
426 Length = 4; Immediate = true;
427 break;
429 case BEN_CONT_OFFSET8_LEN4:
430 case BEN_OFFSET8_LEN4:
431 EightByteOffset = true;
432 break;
434 default:
435 return BenErr_OK;
438 BenByte ImmData[4];
439 if (Immediate && Length != 0)
440 if ((Err = GetData(ImmData, 4)) != BenErr_OK)
441 return Err;
443 *pLookAhead = GetCode();
445 if (EightByteOffset)
446 return BenErr_64BitOffsetNotSupported;
448 if (pValue != nullptr)
450 if (! Immediate)
451 new CBenValueSegment(pValue, Offset, Length);
452 else if (Length != 0)
454 assert(Length <= 4);
455 new CBenValueSegment(pValue, ImmData, static_cast<unsigned short>(Length));
459 return BenErr_OK;
462 bool
463 CBenTOCReader::CanGetData(unsigned long Amt)
465 return cCurr + Amt <= cTOCSize;
468 BenError
469 CBenTOCReader::GetByte(BenByte * pByte)
471 if (! CanGetData(1))
472 return BenErr_ReadPastEndOfTOC;
474 *pByte = UtGetIntelByte(cpTOC.get() + cCurr);
475 ++cCurr;
476 return BenErr_OK;
479 BenError
480 CBenTOCReader::GetDWord(BenDWord * pDWord)
482 if (! CanGetData(4))
483 return BenErr_ReadPastEndOfTOC;
485 *pDWord = UtGetIntelDWord(cpTOC.get() + cCurr);
486 cCurr += 4;
487 return BenErr_OK;
490 BenByte
491 CBenTOCReader::GetCode()
493 BenByte Code;
496 if (GetByte(&Code) != BenErr_OK)
497 return BEN_READ_PAST_END_OF_TOC;
499 if (Code == BEN_END_OF_BUFFER)
500 // Advance to next block
501 cCurr = cBlockSize * ((cCurr + (cBlockSize - 1)) /
502 cBlockSize);
504 while (Code == BEN_NOOP || Code == BEN_END_OF_BUFFER);
505 return Code;
508 BenError
509 CBenTOCReader::GetData(void * pBuffer, unsigned long Amt)
511 if (! CanGetData(Amt))
512 return BenErr_ReadPastEndOfTOC;
514 std::memcpy(pBuffer, cpTOC.get() + cCurr, Amt);
515 cCurr += Amt;
516 return BenErr_OK;
518 }//end OpenStormBento namespace
520 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */