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