cURL: follow redirects
[LibreOffice.git] / lotuswordpro / source / filter / tocread.cxx
blob45c7303d5b62b3dde022ea17e9a2430b22e3d721
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 ************************************************************************/
56 #include "first.hxx"
57 #include "assert.h"
58 namespace OpenStormBento
61 BenError
62 CBenTOCReader::ReadLabelAndTOC()
64 BenError Err;
66 unsigned long TOCOffset;
67 if ((Err = ReadLabel(&TOCOffset, &cTOCSize)) != BenErr_OK)
68 return Err;
70 sal_uLong nLength;
71 if ((Err = cpContainer->GetSize(&nLength)) != BenErr_OK)
72 return Err;
74 if (TOCOffset > nLength)
75 return BenErr_ReadPastEndOfTOC;
77 if (cTOCSize > nLength - TOCOffset)
78 return BenErr_ReadPastEndOfTOC;
80 if ((Err = cpContainer->SeekToPosition(TOCOffset)) != BenErr_OK)
81 return Err;
83 cpTOC.reset( new BenByte[cTOCSize] );
84 if ((Err = cpContainer->ReadKnownSize(cpTOC.get(), cTOCSize)) != BenErr_OK)
85 return Err;
87 if ((Err = ReadTOC()) != BenErr_OK)
88 return Err;
90 return BenErr_OK;
93 BenError
94 CBenTOCReader::ReadLabel(unsigned long * pTOCOffset, unsigned long * pTOCSize)
96 // If seek fails, then probably because stream is smaller than
97 // BEN_LABEL_SIZE and thus can't be Bento container
98 BenError Err;
99 if ((Err = cpContainer->SeekFromEnd(-BEN_LABEL_SIZE)) != BenErr_OK)
100 return BenErr_NotBentoContainer;
102 BenByte Label[BEN_LABEL_SIZE];
103 if ((Err = cpContainer->ReadKnownSize(Label, BEN_LABEL_SIZE)) != BenErr_OK)
104 return Err;
106 if (memcmp(Label, gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) != 0)
107 if ((Err = SearchForLabel(Label)) != BenErr_OK)
108 return Err;
110 BenByte * pCurrLabel = Label + BEN_MAGIC_BYTES_SIZE;
112 BenWord Flags =
113 UtGetIntelWord(pCurrLabel); pCurrLabel += 2; // Flags
114 // Newer files are 0x0101--indicates if big or little endian. Older
115 // files are 0x0 for flags
116 if (Flags != 0x0101 && Flags != 0x0)
117 return BenErr_UnknownBentoFormatVersion;
119 cBlockSize = UtGetIntelWord(pCurrLabel) * 1024; pCurrLabel += 2;
120 if (cBlockSize == 0)
121 return BenErr_NotBentoContainer;
123 // Check major version
124 if (UtGetIntelWord(pCurrLabel) != BEN_CURR_MAJOR_VERSION)
125 return BenErr_UnknownBentoFormatVersion;
126 pCurrLabel += 2;
128 pCurrLabel += 2; // Minor version
130 *pTOCOffset = UtGetIntelDWord(pCurrLabel); pCurrLabel += 4;
131 *pTOCSize = UtGetIntelDWord(pCurrLabel);
133 assert(pCurrLabel + 4 == Label + BEN_LABEL_SIZE);
135 return BenErr_OK;
138 #define LABEL_READ_BUFFER_SIZE 500
139 #define MAX_SEARCH_AMOUNT 1024 * 1024
141 BenError
142 CBenTOCReader::SearchForLabel(BenByte * pLabel)
144 BenError Err;
146 sal_uLong Length;
147 if ((Err = cpContainer->GetSize(&Length)) != BenErr_OK)
148 return Err;
150 // Always ready to check for MagicBytes from
151 // CurrOffset - BEN_MAGIC_BYTES_SIZE to CurrOffset - 1
152 unsigned long CurrOffset = Length - BEN_LABEL_SIZE + BEN_MAGIC_BYTES_SIZE -
155 char Buffer[LABEL_READ_BUFFER_SIZE] = {0};
157 unsigned long BufferStartOffset = Length; // Init to big value
159 while (CurrOffset >= BEN_MAGIC_BYTES_SIZE)
161 // Don't search backwards more than 1 meg
162 if (Length - CurrOffset > MAX_SEARCH_AMOUNT)
163 break;
165 // If before beginning of buffer
166 if (CurrOffset - BEN_MAGIC_BYTES_SIZE < BufferStartOffset)
168 unsigned long UsedBufferSize;
169 if (CurrOffset < LABEL_READ_BUFFER_SIZE)
170 UsedBufferSize = CurrOffset;
171 else UsedBufferSize = LABEL_READ_BUFFER_SIZE;
173 if ((Err = cpContainer->SeekToPosition(CurrOffset - UsedBufferSize))
174 != BenErr_OK)
175 return Err;
177 if ((Err = cpContainer->ReadKnownSize(Buffer, UsedBufferSize)) !=
178 BenErr_OK)
179 return Err;
181 BufferStartOffset = CurrOffset - UsedBufferSize;
184 if (memcmp(Buffer + (CurrOffset - BEN_MAGIC_BYTES_SIZE -
185 BufferStartOffset), gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) == 0)
187 if ((Err = cpContainer->SeekToPosition(CurrOffset -
188 BEN_MAGIC_BYTES_SIZE)) != BenErr_OK)
189 return Err;
191 return cpContainer->ReadKnownSize(pLabel, BEN_LABEL_SIZE);
194 --CurrOffset;
197 return BenErr_NotBentoContainer; // Didn't find magic bytes
200 BenError
201 CBenTOCReader::ReadTOC()
203 BenError Err;
204 BenByte LookAhead = GetCode();
205 BenGeneration Generation = 0;
207 // Read in all objects
208 while (LookAhead == BEN_NEW_OBJECT)
210 BenObjectID ObjectID;
211 if ((Err = GetDWord(&ObjectID)) != BenErr_OK)
212 return Err;
213 pCBenObject pObject = nullptr;
215 // Read in all properties for object
218 BenObjectID PropertyID;
220 if ((Err = GetDWord(&PropertyID)) != BenErr_OK)
221 return Err;
222 pCBenProperty pProperty = nullptr;
224 // Read in all values for property
227 BenObjectID ReferencedListID = 0;
229 BenObjectID TypeID;
230 if ((Err = GetDWord(&TypeID)) != BenErr_OK)
231 return Err;
232 LookAhead = GetCode();
234 if (LookAhead == BEN_EXPLICIT_GEN)
236 if ((Err = GetDWord(&Generation)) != BenErr_OK)
237 return Err;
238 LookAhead = GetCode();
241 if (LookAhead == BEN_REFERENCE_LIST_ID)
243 if ((Err = GetDWord(&ReferencedListID)) != BenErr_OK)
244 return Err;
245 LookAhead = GetCode();
248 if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME ||
249 PropertyID == BEN_PROPID_GLOBAL_TYPE_NAME)
251 // Read property or type name
253 if (pObject != nullptr || TypeID != BEN_TYPEID_7_BIT_ASCII ||
254 LookAhead != BEN_OFFSET4_LEN4)
255 return BenErr_NamedObjectError;
257 BenContainerPos Pos;
258 unsigned long Length;
260 if ((Err = GetDWord(&Pos)) != BenErr_OK)
261 return Err;
262 if ((Err = GetDWord(&Length)) != BenErr_OK)
263 return Err;
264 LookAhead = GetCode();
266 if ((Err = cpContainer->SeekToPosition(Pos)) != BenErr_OK)
267 return Err;
269 #define STACK_BUFFER_SIZE 256
270 char sStackBuffer[STACK_BUFFER_SIZE];
271 char * sAllocBuffer;
272 char * sBuffer;
273 if (Length > STACK_BUFFER_SIZE)
275 sBuffer = new char[Length];
276 sAllocBuffer = sBuffer;
278 else
280 sBuffer = sStackBuffer;
281 sAllocBuffer = nullptr;
284 if ((Err = cpContainer->ReadKnownSize(sBuffer, Length)) !=
285 BenErr_OK)
287 delete[] sAllocBuffer;
288 return Err;
291 OString sName(sBuffer, Length);
293 pCUtListElmt pPrevNamedObjectListElmt;
294 if (FindNamedObject(&cpContainer->GetNamedObjects(),
295 sName, &pPrevNamedObjectListElmt) != nullptr)
297 delete[] sAllocBuffer;
298 return BenErr_DuplicateName;
301 pCBenObject pPrevObject = static_cast<pCBenObject>( cpContainer->
302 GetObjects().GetLast());
304 if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME)
305 pObject = new CBenPropertyName(cpContainer, ObjectID,
306 pPrevObject, sName, pPrevNamedObjectListElmt);
307 else pObject = new CBenTypeName(cpContainer, ObjectID,
308 pPrevObject, sName, pPrevNamedObjectListElmt);
310 delete[] sAllocBuffer;
312 else if (PropertyID == BEN_PROPID_OBJ_REFERENCES)
314 // Don't need to read in references object--we assume
315 // that all references use object ID as key
316 if ((Err = ReadSegments(nullptr, &LookAhead)) != BenErr_OK)
317 return Err;
319 else if (ObjectID == BEN_OBJID_TOC)
321 if (PropertyID == BEN_PROPID_TOC_SEED)
323 if (TypeID != BEN_TYPEID_TOC_TYPE ||
324 LookAhead != BEN_IMMEDIATE4)
325 return BenErr_TOCSeedError;
327 BenDWord Data;
328 if ((Err = GetDWord(&Data)) != BenErr_OK)
329 return Err;
330 LookAhead = GetCode();
332 cpContainer->SetNextAvailObjectID(Data);
334 else
336 // Ignore the other BEN_OBJID_TOC properties
337 if ((Err = ReadSegments(nullptr, &LookAhead)) != BenErr_OK)
338 return Err;
341 else
343 if (pProperty != nullptr)
344 return BenErr_PropertyWithMoreThanOneValue;
346 if (pObject == nullptr)
347 pObject = new CBenObject(cpContainer, ObjectID,
348 cpContainer->GetObjects().GetLast());
350 pProperty = new CBenProperty(pObject, PropertyID, TypeID,
351 pObject->GetProperties().GetLast());
353 if ((Err = ReadSegments(&pProperty->UseValue(),
354 &LookAhead)) != BenErr_OK)
355 return Err;
357 } while (LookAhead == BEN_NEW_TYPE);
358 } while (LookAhead == BEN_NEW_PROPERTY);
361 if (LookAhead == BEN_READ_PAST_END_OF_TOC)
362 return BenErr_OK;
363 else return BenErr_InvalidTOC;
366 BenError
367 CBenTOCReader::ReadSegments(pCBenValue pValue, BenByte * pLookAhead)
369 BenError Err;
371 while (*pLookAhead >= BEN_SEGMENT_CODE_START &&
372 *pLookAhead <= BEN_SEGMENT_CODE_END)
374 if ((Err = ReadSegment(pValue, pLookAhead)) !=
375 BenErr_OK)
376 return Err;
379 return BenErr_OK;
382 BenError
383 CBenTOCReader::ReadSegment(pCBenValue pValue, BenByte * pLookAhead)
385 BenError Err;
387 bool Immediate = false;
388 bool EightByteOffset = false;
389 unsigned long Offset(0), Length(0);
391 switch (*pLookAhead)
393 case BEN_CONT_OFFSET4_LEN4:
394 case BEN_OFFSET4_LEN4:
395 if ((Err = GetDWord(&Offset)) != BenErr_OK)
396 return Err;
397 if ((Err = GetDWord(&Length)) != BenErr_OK)
398 return Err;
399 break;
401 case BEN_IMMEDIATE0:
402 Length = 0; Immediate = true;
403 break;
405 case BEN_IMMEDIATE1:
406 Length = 1; Immediate = true;
407 break;
409 case BEN_IMMEDIATE2:
410 Length = 2; Immediate = true;
411 break;
413 case BEN_IMMEDIATE3:
414 Length = 3; Immediate = true;
415 break;
417 case BEN_CONT_IMMEDIATE4:
418 case BEN_IMMEDIATE4:
419 Length = 4; Immediate = true;
420 break;
422 case BEN_CONT_OFFSET8_LEN4:
423 case BEN_OFFSET8_LEN4:
424 EightByteOffset = true;
425 break;
427 default:
428 return BenErr_OK;
431 BenByte ImmData[4];
432 if (Immediate && Length != 0)
433 if ((Err = GetData(ImmData, 4)) != BenErr_OK)
434 return Err;
436 *pLookAhead = GetCode();
438 if (EightByteOffset)
439 return BenErr_64BitOffsetNotSupported;
441 if (pValue != nullptr)
443 if (! Immediate)
444 new CBenValueSegment(pValue, Offset, Length);
445 else if (Length != 0)
447 assert(Length <= 4);
448 new CBenValueSegment(pValue, ImmData, (unsigned short) Length);
452 return BenErr_OK;
455 bool
456 CBenTOCReader::CanGetData(unsigned long Amt)
458 return cCurr + Amt <= cTOCSize;
461 BenError
462 CBenTOCReader::GetByte(BenByte * pByte)
464 if (! CanGetData(1))
465 return BenErr_ReadPastEndOfTOC;
467 *pByte = UtGetIntelByte(cpTOC.get() + cCurr);
468 ++cCurr;
469 return BenErr_OK;
472 BenError
473 CBenTOCReader::GetDWord(BenDWord * pDWord)
475 if (! CanGetData(4))
476 return BenErr_ReadPastEndOfTOC;
478 *pDWord = UtGetIntelDWord(cpTOC.get() + cCurr);
479 cCurr += 4;
480 return BenErr_OK;
483 BenByte
484 CBenTOCReader::GetCode()
486 BenByte Code;
489 if (GetByte(&Code) != BenErr_OK)
490 return BEN_READ_PAST_END_OF_TOC;
492 if (Code == BEN_END_OF_BUFFER)
493 // Advance to next block
494 cCurr = cBlockSize * ((cCurr + (cBlockSize - 1)) /
495 cBlockSize);
497 while (Code == BEN_NOOP || Code == BEN_END_OF_BUFFER);
498 return Code;
501 BenError
502 CBenTOCReader::GetData(void * pBuffer, unsigned long Amt)
504 if (! CanGetData(Amt))
505 return BenErr_ReadPastEndOfTOC;
507 UtHugeMemcpy(pBuffer, cpTOC.get() + cCurr, Amt);
508 cCurr += Amt;
509 return BenErr_OK;
511 }//end OpenStormBento namespace
513 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */