Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*************************************************************************
3 : *
4 : * The Contents of this file are made available subject to the terms of
5 : * either of the following licenses
6 : *
7 : * - GNU Lesser General Public License Version 2.1
8 : * - Sun Industry Standards Source License Version 1.1
9 : *
10 : * Sun Microsystems Inc., October, 2000
11 : *
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
16 : *
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.
20 : *
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.
25 : *
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
30 : *
31 : *
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.
38 : *
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.
45 : *
46 : * The Initial Developer of the Original Code is: IBM Corporation
47 : *
48 : * Copyright: 2008 by IBM Corporation
49 : *
50 : * All Rights Reserved.
51 : *
52 : * Contributor(s): _______________________________________
53 : *
54 : *
55 : ************************************************************************/
56 : #include "first.hxx"
57 : #include "assert.h"
58 : namespace OpenStormBento
59 : {
60 :
61 : BenError
62 8 : CBenTOCReader::ReadLabelAndTOC()
63 : {
64 : BenError Err;
65 :
66 : unsigned long TOCOffset;
67 8 : if ((Err = ReadLabel(&TOCOffset, &cTOCSize)) != BenErr_OK)
68 0 : return Err;
69 :
70 : unsigned long nLength;
71 8 : if ((Err = cpContainer->GetSize(&nLength)) != BenErr_OK)
72 0 : return Err;
73 :
74 8 : if (TOCOffset > nLength)
75 0 : return BenErr_ReadPastEndOfTOC;
76 :
77 8 : if (cTOCSize > nLength - TOCOffset)
78 0 : return BenErr_ReadPastEndOfTOC;
79 :
80 8 : if ((Err = cpContainer->SeekToPosition(TOCOffset)) != BenErr_OK)
81 0 : return Err;
82 :
83 8 : cpTOC = new BenByte[cTOCSize];
84 8 : if ((Err = cpContainer->ReadKnownSize(cpTOC, cTOCSize)) != BenErr_OK)
85 0 : return Err;
86 :
87 8 : if ((Err = ReadTOC()) != BenErr_OK)
88 0 : return Err;
89 :
90 8 : return BenErr_OK;
91 : }
92 :
93 : BenError
94 8 : CBenTOCReader::ReadLabel(unsigned long * pTOCOffset, unsigned long * pTOCSize)
95 : {
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 8 : if ((Err = cpContainer->SeekFromEnd(-BEN_LABEL_SIZE)) != BenErr_OK)
100 0 : return BenErr_NotBentoContainer;
101 :
102 : BenByte Label[BEN_LABEL_SIZE];
103 8 : if ((Err = cpContainer->ReadKnownSize(Label, BEN_LABEL_SIZE)) != BenErr_OK)
104 0 : return Err;
105 :
106 8 : if (memcmp(Label, gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) != 0)
107 0 : if ((Err = SearchForLabel(Label)) != BenErr_OK)
108 0 : return Err;
109 :
110 8 : BenByte * pCurrLabel = Label + BEN_MAGIC_BYTES_SIZE;
111 :
112 : #ifndef NDEBUG
113 : BenWord Flags =
114 : #endif
115 8 : UtGetIntelWord(pCurrLabel); pCurrLabel += 2; // Flags
116 : // Newer files are 0x0101--indicates if big or little endian. Older
117 : // files are 0x0 for flags
118 : assert(Flags == 0x0101 || Flags == 0x0);
119 :
120 8 : cBlockSize = UtGetIntelWord(pCurrLabel) * 1024; pCurrLabel += 2;
121 :
122 : // Check major version
123 8 : if (UtGetIntelWord(pCurrLabel) != BEN_CURR_MAJOR_VERSION)
124 0 : return BenErr_UnknownBentoFormatVersion;
125 8 : pCurrLabel += 2;
126 :
127 8 : UtGetIntelWord(pCurrLabel); pCurrLabel += 2; // Minor version
128 :
129 8 : *pTOCOffset = UtGetIntelDWord(pCurrLabel); pCurrLabel += 4;
130 8 : *pTOCSize = UtGetIntelDWord(pCurrLabel);
131 :
132 : assert(pCurrLabel + 4 == Label + BEN_LABEL_SIZE);
133 :
134 8 : return BenErr_OK;
135 : }
136 :
137 : #define LABEL_READ_BUFFER_SIZE 500
138 : #define MAX_SEARCH_AMOUNT 1024 * 1024
139 :
140 : BenError
141 0 : CBenTOCReader::SearchForLabel(BenByte * pLabel)
142 : {
143 : BenError Err;
144 :
145 : sal_uLong Length;
146 0 : if ((Err = cpContainer->GetSize(&Length)) != BenErr_OK)
147 0 : return Err;
148 :
149 : // Always ready to check for MagicBytes from
150 : // CurrOffset - BEN_MAGIC_BYTES_SIZE to CurrOffset - 1
151 0 : unsigned long CurrOffset = Length - BEN_LABEL_SIZE + BEN_MAGIC_BYTES_SIZE -
152 0 : 1;
153 :
154 0 : char Buffer[LABEL_READ_BUFFER_SIZE] = {0};
155 :
156 0 : unsigned long BufferStartOffset = Length; // Init to big value
157 :
158 0 : while (CurrOffset >= BEN_MAGIC_BYTES_SIZE)
159 : {
160 : // Don't search backwards more than 1 meg
161 0 : if (Length - CurrOffset > MAX_SEARCH_AMOUNT)
162 0 : break;
163 :
164 : // If before beginning of buffer
165 0 : if (CurrOffset - BEN_MAGIC_BYTES_SIZE < BufferStartOffset)
166 : {
167 : unsigned long UsedBufferSize;
168 0 : if (CurrOffset < LABEL_READ_BUFFER_SIZE)
169 0 : UsedBufferSize = CurrOffset;
170 0 : else UsedBufferSize = LABEL_READ_BUFFER_SIZE;
171 :
172 0 : if ((Err = cpContainer->SeekToPosition(CurrOffset - UsedBufferSize))
173 : != BenErr_OK)
174 0 : return Err;
175 :
176 0 : if ((Err = cpContainer->ReadKnownSize(Buffer, UsedBufferSize)) !=
177 : BenErr_OK)
178 0 : return Err;
179 :
180 0 : BufferStartOffset = CurrOffset - UsedBufferSize;
181 : }
182 :
183 0 : if (memcmp(Buffer + (CurrOffset - BEN_MAGIC_BYTES_SIZE -
184 0 : BufferStartOffset), gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) == 0)
185 : {
186 0 : if ((Err = cpContainer->SeekToPosition(CurrOffset -
187 0 : BEN_MAGIC_BYTES_SIZE)) != BenErr_OK)
188 0 : return Err;
189 :
190 0 : return cpContainer->ReadKnownSize(pLabel, BEN_LABEL_SIZE);
191 : }
192 :
193 0 : --CurrOffset;
194 : }
195 :
196 0 : return BenErr_NotBentoContainer; // Didn't find magic bytes
197 : }
198 :
199 : BenError
200 8 : CBenTOCReader::ReadTOC()
201 : {
202 : BenError Err;
203 8 : BenByte LookAhead = GetCode();
204 8 : BenGeneration Generation = 0;
205 :
206 : // Read in all objects
207 476 : while (LookAhead == BEN_NEW_OBJECT)
208 : {
209 : BenObjectID ObjectID;
210 460 : if ((Err = GetDWord(&ObjectID)) != BenErr_OK)
211 0 : return Err;
212 460 : pCBenObject pObject = NULL;
213 :
214 : // Read in all properties for object
215 554 : do
216 : {
217 : BenObjectID PropertyID;
218 :
219 554 : if ((Err = GetDWord(&PropertyID)) != BenErr_OK)
220 0 : return Err;
221 554 : pCBenProperty pProperty = NULL;
222 :
223 : // Read in all values for property
224 554 : do
225 : {
226 554 : BenObjectID ReferencedListID = 0;
227 :
228 : BenObjectID TypeID;
229 554 : if ((Err = GetDWord(&TypeID)) != BenErr_OK)
230 0 : return Err;
231 554 : LookAhead = GetCode();
232 :
233 554 : if (LookAhead == BEN_EXPLICIT_GEN)
234 : {
235 14 : if ((Err = GetDWord(&Generation)) != BenErr_OK)
236 0 : return Err;
237 14 : LookAhead = GetCode();
238 : }
239 :
240 554 : if (LookAhead == BEN_REFERENCE_LIST_ID)
241 : {
242 60 : if ((Err = GetDWord(&ReferencedListID)) != BenErr_OK)
243 0 : return Err;
244 60 : LookAhead = GetCode();
245 : }
246 :
247 1020 : if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME ||
248 466 : PropertyID == BEN_PROPID_GLOBAL_TYPE_NAME)
249 : {
250 : // Read property or type name
251 :
252 216 : if (pObject != NULL || TypeID != BEN_TYPEID_7_BIT_ASCII ||
253 108 : LookAhead != BEN_OFFSET4_LEN4)
254 0 : return BenErr_NamedObjectError;
255 :
256 : BenContainerPos Pos;
257 : unsigned long Length;
258 :
259 108 : if ((Err = GetDWord(&Pos)) != BenErr_OK)
260 0 : return Err;
261 108 : if ((Err = GetDWord(&Length)) != BenErr_OK)
262 0 : return Err;
263 108 : LookAhead = GetCode();
264 :
265 108 : if ((Err = cpContainer->SeekToPosition(Pos)) != BenErr_OK)
266 0 : return Err;
267 :
268 : #define STACK_BUFFER_SIZE 256
269 : char sStackBuffer[STACK_BUFFER_SIZE];
270 : char * sAllocBuffer;
271 : char * sBuffer;
272 108 : if (Length > STACK_BUFFER_SIZE)
273 : {
274 0 : sBuffer = new char[Length];
275 0 : sAllocBuffer = sBuffer;
276 : }
277 : else
278 : {
279 108 : sBuffer = sStackBuffer;
280 108 : sAllocBuffer = NULL;
281 : }
282 :
283 108 : if ((Err = cpContainer->ReadKnownSize(sBuffer, Length)) !=
284 : BenErr_OK)
285 : {
286 0 : delete[] sAllocBuffer;
287 0 : return Err;
288 : }
289 :
290 : pCUtListElmt pPrevNamedObjectListElmt;
291 216 : if (FindNamedObject(&cpContainer->GetNamedObjects(),
292 108 : sBuffer, &pPrevNamedObjectListElmt) != NULL)
293 : {
294 0 : delete[] sAllocBuffer;
295 0 : return BenErr_DuplicateName;
296 : }
297 :
298 : pCBenObject pPrevObject = static_cast<pCBenObject>( cpContainer->
299 108 : GetObjects().GetLast());
300 :
301 108 : if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME)
302 : pObject = new CBenPropertyName(cpContainer, ObjectID,
303 88 : pPrevObject, sBuffer, pPrevNamedObjectListElmt);
304 : else pObject = new CBenTypeName(cpContainer, ObjectID,
305 20 : pPrevObject, sBuffer, pPrevNamedObjectListElmt);
306 :
307 108 : delete[] sAllocBuffer;
308 : }
309 446 : else if (PropertyID == BEN_PROPID_OBJ_REFERENCES)
310 : {
311 : // Don't need to read in references object--we assume
312 : // that all references use object ID as key
313 60 : if ((Err = ReadSegments(NULL, &LookAhead)) != BenErr_OK)
314 0 : return Err;
315 : }
316 386 : else if (ObjectID == BEN_OBJID_TOC)
317 : {
318 40 : if (PropertyID == BEN_PROPID_TOC_SEED)
319 : {
320 16 : if (TypeID != BEN_TYPEID_TOC_TYPE ||
321 8 : LookAhead != BEN_IMMEDIATE4)
322 0 : return BenErr_TOCSeedError;
323 :
324 : BenDWord Data;
325 8 : if ((Err = GetDWord(&Data)) != BenErr_OK)
326 0 : return Err;
327 8 : LookAhead = GetCode();
328 :
329 8 : cpContainer->SetNextAvailObjectID(Data);
330 : }
331 : else
332 : {
333 : // Ignore the other BEN_OBJID_TOC properties
334 32 : if ((Err = ReadSegments(NULL, &LookAhead)) != BenErr_OK)
335 0 : return Err;
336 : }
337 : }
338 : else
339 : {
340 346 : if (pProperty != NULL)
341 0 : return BenErr_PropertyWithMoreThanOneValue;
342 :
343 346 : if (pObject == NULL)
344 : pObject = new CBenObject(cpContainer, ObjectID,
345 284 : cpContainer->GetObjects().GetLast());
346 :
347 : pProperty = new CBenProperty(pObject, PropertyID, TypeID,
348 346 : pObject->GetProperties().GetLast());
349 :
350 346 : if ((Err = ReadSegments(&pProperty->UseValue(),
351 : &LookAhead)) != BenErr_OK)
352 0 : return Err;
353 : }
354 554 : } while (LookAhead == BEN_NEW_TYPE);
355 554 : } while (LookAhead == BEN_NEW_PROPERTY);
356 : }
357 :
358 8 : if (LookAhead == BEN_READ_PAST_END_OF_TOC)
359 8 : return BenErr_OK;
360 0 : else return BenErr_InvalidTOC;
361 : }
362 :
363 : BenError
364 438 : CBenTOCReader::ReadSegments(pCBenValue pValue, BenByte * pLookAhead)
365 : {
366 : BenError Err;
367 :
368 1758 : while (*pLookAhead >= BEN_SEGMENT_CODE_START &&
369 444 : *pLookAhead <= BEN_SEGMENT_CODE_END)
370 : {
371 438 : if ((Err = ReadSegment(pValue, pLookAhead)) !=
372 : BenErr_OK)
373 0 : return Err;
374 : }
375 :
376 438 : return BenErr_OK;
377 : }
378 :
379 : BenError
380 438 : CBenTOCReader::ReadSegment(pCBenValue pValue, BenByte * pLookAhead)
381 : {
382 : BenError Err;
383 :
384 438 : bool Immediate = false;
385 438 : bool EightByteOffset = false;
386 438 : unsigned long Offset(0), Length(0);
387 :
388 438 : switch (*pLookAhead)
389 : {
390 : case BEN_CONT_OFFSET4_LEN4:
391 : case BEN_OFFSET4_LEN4:
392 422 : if ((Err = GetDWord(&Offset)) != BenErr_OK)
393 0 : return Err;
394 422 : if ((Err = GetDWord(&Length)) != BenErr_OK)
395 0 : return Err;
396 422 : break;
397 :
398 : case BEN_IMMEDIATE0:
399 0 : Length = 0; Immediate = true;
400 0 : break;
401 :
402 : case BEN_IMMEDIATE1:
403 0 : Length = 1; Immediate = true;
404 0 : break;
405 :
406 : case BEN_IMMEDIATE2:
407 0 : Length = 2; Immediate = true;
408 0 : break;
409 :
410 : case BEN_IMMEDIATE3:
411 0 : Length = 3; Immediate = true;
412 0 : break;
413 :
414 : case BEN_CONT_IMMEDIATE4:
415 : case BEN_IMMEDIATE4:
416 16 : Length = 4; Immediate = true;
417 16 : break;
418 :
419 : case BEN_CONT_OFFSET8_LEN4:
420 : case BEN_OFFSET8_LEN4:
421 0 : EightByteOffset = true;
422 0 : break;
423 :
424 : default:
425 0 : return BenErr_OK;
426 : }
427 :
428 : BenByte ImmData[4];
429 438 : if (Immediate && Length != 0)
430 16 : if ((Err = GetData(ImmData, 4)) != BenErr_OK)
431 0 : return Err;
432 :
433 438 : *pLookAhead = GetCode();
434 :
435 438 : if (EightByteOffset)
436 0 : return BenErr_64BitOffsetNotSupported;
437 :
438 438 : if (pValue != NULL)
439 : {
440 346 : if (! Immediate)
441 346 : new CBenValueSegment(pValue, Offset, Length);
442 0 : else if (Length != 0)
443 : {
444 : assert(Length <= 4);
445 0 : new CBenValueSegment(pValue, ImmData, (unsigned short) Length);
446 : }
447 : }
448 :
449 438 : return BenErr_OK;
450 : }
451 :
452 : bool
453 3930 : CBenTOCReader::CanGetData(unsigned long Amt)
454 : {
455 3930 : return cCurr + Amt <= cTOCSize;
456 : }
457 :
458 : BenError
459 1204 : CBenTOCReader::GetByte(BenByte * pByte)
460 : {
461 1204 : if (! CanGetData(1))
462 8 : return BenErr_ReadPastEndOfTOC;
463 :
464 1196 : *pByte = UtGetIntelByte(cpTOC + cCurr);
465 1196 : ++cCurr;
466 1196 : return BenErr_OK;
467 : }
468 :
469 : BenError
470 2710 : CBenTOCReader::GetDWord(BenDWord * pDWord)
471 : {
472 2710 : if (! CanGetData(4))
473 0 : return BenErr_ReadPastEndOfTOC;
474 :
475 2710 : *pDWord = UtGetIntelDWord(cpTOC + cCurr);
476 2710 : cCurr += 4;
477 2710 : return BenErr_OK;
478 : }
479 :
480 : BenByte
481 1204 : CBenTOCReader::GetCode()
482 : {
483 : BenByte Code;
484 1196 : do
485 : {
486 1204 : if (GetByte(&Code) != BenErr_OK)
487 8 : return BEN_READ_PAST_END_OF_TOC;
488 :
489 1196 : if (Code == BEN_END_OF_BUFFER)
490 : // Advance to next block
491 14 : cCurr = cBlockSize * ((cCurr + (cBlockSize - 1)) /
492 14 : cBlockSize);
493 : }
494 2392 : while (Code == BEN_NOOP || Code == BEN_END_OF_BUFFER);
495 1182 : return Code;
496 : }
497 :
498 : BenError
499 16 : CBenTOCReader::GetData(BenDataPtr pBuffer, unsigned long Amt)
500 : {
501 16 : if (! CanGetData(Amt))
502 0 : return BenErr_ReadPastEndOfTOC;
503 :
504 16 : UtHugeMemcpy(pBuffer, cpTOC + cCurr, Amt);
505 16 : cCurr += Amt;
506 16 : return BenErr_OK;
507 : }
508 : }//end OpenStormBento namespace
509 :
510 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|