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