tdf#131098 docx export: write fill property of graphic
[LibreOffice.git] / lotuswordpro / source / filter / tocread.cxx
blobb9bc3ac9277c750f0c78cae44681370143866546
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>
58 #include <sal/log.hxx>
60 #include <cstring>
62 #include "first.hxx"
63 #include "bentoid.hxx"
64 #include "tocread.hxx"
65 #include "ut.hxx"
66 #include <assert.h>
67 namespace OpenStormBento
70 BenError
71 CBenTOCReader::ReadLabelAndTOC()
73 BenError Err;
75 tools::ULong TOCOffset;
76 if ((Err = ReadLabel(&TOCOffset, &cTOCSize)) != BenErr_OK)
77 return Err;
79 sal_uInt64 nLength = cpContainer->GetSize();
81 if (TOCOffset > nLength)
82 return BenErr_ReadPastEndOfTOC;
84 if (cTOCSize > nLength - TOCOffset)
85 return BenErr_ReadPastEndOfTOC;
87 cpContainer->SeekToPosition(TOCOffset);
89 cpTOC.reset( new BenByte[cTOCSize] );
90 if ((Err = cpContainer->ReadKnownSize(cpTOC.get(), cTOCSize)) != BenErr_OK)
91 return Err;
93 if ((Err = ReadTOC()) != BenErr_OK)
94 return Err;
96 return BenErr_OK;
99 BenError
100 CBenTOCReader::ReadLabel(tools::ULong * pTOCOffset, tools::ULong * pTOCSize)
102 // If seek fails, then probably because stream is smaller than
103 // BEN_LABEL_SIZE and thus can't be Bento container
104 BenError Err;
105 cpContainer->SeekFromEnd(-BEN_LABEL_SIZE);
107 BenByte Label[BEN_LABEL_SIZE];
108 if ((Err = cpContainer->ReadKnownSize(Label, BEN_LABEL_SIZE)) != BenErr_OK)
109 return Err;
111 if (memcmp(Label, gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) != 0)
112 if ((Err = SearchForLabel(Label)) != BenErr_OK)
113 return Err;
115 BenByte * pCurrLabel = Label + BEN_MAGIC_BYTES_SIZE;
117 BenWord Flags =
118 UtGetIntelWord(pCurrLabel);
119 pCurrLabel += 2; // Flags
120 // Newer files are 0x0101--indicates if big or little endian. Older
121 // files are 0x0 for flags
122 if (Flags != 0x0101 && Flags != 0x0)
123 return BenErr_UnknownBentoFormatVersion;
125 cBlockSize = UtGetIntelWord(pCurrLabel) * 1024; pCurrLabel += 2;
126 if (cBlockSize == 0)
127 return BenErr_NotBentoContainer;
129 // Check major version
130 if (UtGetIntelWord(pCurrLabel) != BEN_CURR_MAJOR_VERSION)
131 return BenErr_UnknownBentoFormatVersion;
132 pCurrLabel += 2;
134 pCurrLabel += 2; // Minor version
136 *pTOCOffset = UtGetIntelDWord(pCurrLabel); pCurrLabel += 4;
137 *pTOCSize = UtGetIntelDWord(pCurrLabel);
139 assert(pCurrLabel + 4 == Label + BEN_LABEL_SIZE);
141 return BenErr_OK;
144 #define LABEL_READ_BUFFER_SIZE 500
145 #define MAX_SEARCH_AMOUNT 1024 * 1024
147 BenError
148 CBenTOCReader::SearchForLabel(BenByte * pLabel)
150 BenError Err;
152 sal_uInt64 Length = cpContainer->GetSize();
154 // Always ready to check for MagicBytes from
155 // CurrOffset - BEN_MAGIC_BYTES_SIZE to CurrOffset - 1
156 unsigned long CurrOffset = Length - BEN_LABEL_SIZE + BEN_MAGIC_BYTES_SIZE -
159 char Buffer[LABEL_READ_BUFFER_SIZE] = {0};
161 unsigned long BufferStartOffset = Length; // Init to big value
163 while (CurrOffset >= BEN_MAGIC_BYTES_SIZE)
165 // Don't search backwards more than 1 meg
166 if (Length - CurrOffset > MAX_SEARCH_AMOUNT)
167 break;
169 // If before beginning of buffer
170 if (CurrOffset - BEN_MAGIC_BYTES_SIZE < BufferStartOffset)
172 unsigned long UsedBufferSize;
173 if (CurrOffset < LABEL_READ_BUFFER_SIZE)
174 UsedBufferSize = CurrOffset;
175 else UsedBufferSize = LABEL_READ_BUFFER_SIZE;
177 cpContainer->SeekToPosition(CurrOffset - UsedBufferSize);
179 if ((Err = cpContainer->ReadKnownSize(Buffer, UsedBufferSize)) !=
180 BenErr_OK)
181 return Err;
183 BufferStartOffset = CurrOffset - UsedBufferSize;
186 if (memcmp(Buffer + (CurrOffset - BEN_MAGIC_BYTES_SIZE -
187 BufferStartOffset), gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) == 0)
189 cpContainer->SeekToPosition(CurrOffset -
190 BEN_MAGIC_BYTES_SIZE);
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 cpContainer->SeekToPosition(Pos);
269 const auto nRemainingSize = cpContainer->remainingSize();
270 if (Length > nRemainingSize)
272 SAL_WARN("lwp", "stream too short for claimed no of records");
273 Length = nRemainingSize;
276 #define STACK_BUFFER_SIZE 256
277 char sStackBuffer[STACK_BUFFER_SIZE];
278 std::unique_ptr<char[]> sAllocBuffer;
279 char * sBuffer;
280 if (Length > STACK_BUFFER_SIZE)
282 sAllocBuffer.reset(new char[Length]);
283 sBuffer = sAllocBuffer.get();
285 else
287 sBuffer = sStackBuffer;
290 if ((Err = cpContainer->ReadKnownSize(sBuffer, Length)) !=
291 BenErr_OK)
293 return Err;
296 OString sName;
297 if (Length)
298 sName = OString(sBuffer, Length - 1);
300 CUtListElmt * pPrevNamedObjectListElmt;
301 if (FindNamedObject(&cpContainer->GetNamedObjects(),
302 sName, &pPrevNamedObjectListElmt) != nullptr)
304 return BenErr_DuplicateName;
307 CUtListElmt* pPrevObject = cpContainer->GetObjects().GetLast();
309 if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME)
310 pObject = new CBenPropertyName(cpContainer, ObjectID,
311 pPrevObject, sName, pPrevNamedObjectListElmt);
312 else
313 pObject = new CBenTypeName(cpContainer, ObjectID,
314 pPrevObject, sName, pPrevNamedObjectListElmt);
316 else if (PropertyID == BEN_PROPID_OBJ_REFERENCES)
318 // Don't need to read in references object--we assume
319 // that all references use object ID as key
320 if ((Err = ReadSegments(nullptr, &LookAhead)) != BenErr_OK)
321 return Err;
323 else if (ObjectID == BEN_OBJID_TOC)
325 if (PropertyID == BEN_PROPID_TOC_SEED)
327 if (TypeID != BEN_TYPEID_TOC_TYPE ||
328 LookAhead != BEN_IMMEDIATE4)
329 return BenErr_TOCSeedError;
331 BenDWord Data;
332 if ((Err = GetDWord(&Data)) != BenErr_OK)
333 return Err;
334 LookAhead = GetCode();
336 cpContainer->SetNextAvailObjectID(Data);
338 else
340 // Ignore the other BEN_OBJID_TOC properties
341 if ((Err = ReadSegments(nullptr, &LookAhead)) != BenErr_OK)
342 return Err;
345 else
347 if (pProperty != nullptr)
348 return BenErr_PropertyWithMoreThanOneValue;
350 if (pObject == nullptr)
351 pObject = new CBenObject(cpContainer, ObjectID,
352 cpContainer->GetObjects().GetLast());
354 pProperty = new CBenProperty(pObject, PropertyID, TypeID,
355 pObject->GetProperties().GetLast());
357 if ((Err = ReadSegments(&pProperty->UseValue(),
358 &LookAhead)) != BenErr_OK)
359 return Err;
361 } while (LookAhead == BEN_NEW_TYPE);
362 } while (LookAhead == BEN_NEW_PROPERTY);
365 if (LookAhead == BEN_READ_PAST_END_OF_TOC)
366 return BenErr_OK;
367 else return BenErr_InvalidTOC;
370 BenError
371 CBenTOCReader::ReadSegments(CBenValue * pValue, BenByte * pLookAhead)
373 BenError Err;
375 while (*pLookAhead >= BEN_SEGMENT_CODE_START &&
376 *pLookAhead <= BEN_SEGMENT_CODE_END)
378 if ((Err = ReadSegment(pValue, pLookAhead)) !=
379 BenErr_OK)
380 return Err;
383 return BenErr_OK;
386 BenError
387 CBenTOCReader::ReadSegment(CBenValue * pValue, BenByte * pLookAhead)
389 BenError Err;
391 bool Immediate = false;
392 bool EightByteOffset = false;
393 sal_uInt32 Offset(0), Length(0);
395 switch (*pLookAhead)
397 case BEN_CONT_OFFSET4_LEN4:
398 case BEN_OFFSET4_LEN4:
399 if ((Err = GetDWord(&Offset)) != BenErr_OK)
400 return Err;
401 if ((Err = GetDWord(&Length)) != BenErr_OK)
402 return Err;
403 break;
405 case BEN_IMMEDIATE0:
406 Length = 0; Immediate = true;
407 break;
409 case BEN_IMMEDIATE1:
410 Length = 1; Immediate = true;
411 break;
413 case BEN_IMMEDIATE2:
414 Length = 2; Immediate = true;
415 break;
417 case BEN_IMMEDIATE3:
418 Length = 3; Immediate = true;
419 break;
421 case BEN_CONT_IMMEDIATE4:
422 case BEN_IMMEDIATE4:
423 Length = 4; Immediate = true;
424 break;
426 case BEN_CONT_OFFSET8_LEN4:
427 case BEN_OFFSET8_LEN4:
428 EightByteOffset = true;
429 break;
431 default:
432 return BenErr_OK;
435 BenByte ImmData[4];
436 if (Immediate && Length != 0)
437 if ((Err = GetData(ImmData, 4)) != BenErr_OK)
438 return Err;
440 *pLookAhead = GetCode();
442 if (EightByteOffset)
443 return BenErr_64BitOffsetNotSupported;
445 if (pValue != nullptr)
447 if (! Immediate)
448 new CBenValueSegment(pValue, Offset, Length);
449 else if (Length != 0)
451 assert(Length <= 4);
452 new CBenValueSegment(pValue, ImmData, static_cast<unsigned short>(Length));
456 return BenErr_OK;
459 bool
460 CBenTOCReader::CanGetData(tools::ULong Amt)
462 return cCurr + Amt <= cTOCSize;
465 BenError
466 CBenTOCReader::GetByte(BenByte * pByte)
468 if (! CanGetData(1))
469 return BenErr_ReadPastEndOfTOC;
471 *pByte = UtGetIntelByte(cpTOC.get() + cCurr);
472 ++cCurr;
473 return BenErr_OK;
476 BenError
477 CBenTOCReader::GetDWord(BenDWord * pDWord)
479 if (! CanGetData(4))
480 return BenErr_ReadPastEndOfTOC;
482 *pDWord = UtGetIntelDWord(cpTOC.get() + cCurr);
483 cCurr += 4;
484 return BenErr_OK;
487 BenByte
488 CBenTOCReader::GetCode()
490 BenByte Code;
493 if (GetByte(&Code) != BenErr_OK)
494 return BEN_READ_PAST_END_OF_TOC;
496 if (Code == BEN_END_OF_BUFFER)
498 assert(cBlockSize && "cBlockSize of 0 should have already caused BenErr_UnknownBentoFormatVersion in CBenTOCReader::ReadLabel");
499 // Advance to next block
500 cCurr = cBlockSize * ((cCurr + (cBlockSize - 1)) /
501 cBlockSize);
504 while (Code == BEN_NOOP || Code == BEN_END_OF_BUFFER);
505 return Code;
508 BenError
509 CBenTOCReader::GetData(void * pBuffer, tools::ULong 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: */