xref: /aoo42x/main/sd/source/filter/ppt/propread.cxx (revision 79aad27f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 #include <propread.hxx>
27 #include <tools/bigint.hxx>
28 #include "tools/debug.hxx"
29 #include "rtl/tencinfo.h"
30 #include "rtl/textenc.h"
31 
32 // ------------------------------------------------------------------------
33 
34 struct PropEntry
35 {
36 	sal_uInt32	mnId;
37 	sal_uInt32	mnSize;
38 	sal_uInt16	mnTextEnc;
39 	sal_uInt8*	mpBuf;
40 
41 						PropEntry( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize, sal_uInt16 nTextEnc );
42 						PropEntry( const PropEntry& rProp );
~PropEntryPropEntry43 						~PropEntry() { delete[] mpBuf; } ;
44 
45 	const PropEntry&	operator=(const PropEntry& rPropEntry);
46 };
47 
PropEntry(sal_uInt32 nId,const sal_uInt8 * pBuf,sal_uInt32 nBufSize,sal_uInt16 nTextEnc)48 PropEntry::PropEntry( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize, sal_uInt16 nTextEnc ) :
49 	mnId		( nId ),
50 	mnSize		( nBufSize ),
51 	mnTextEnc	( nTextEnc ),
52 	mpBuf		( new sal_uInt8[ nBufSize ] )
53 {
54 	memcpy( (void*)mpBuf, (void*)pBuf, nBufSize );
55 };
56 
PropEntry(const PropEntry & rProp)57 PropEntry::PropEntry( const PropEntry& rProp ) :
58 	mnId		( rProp.mnId ),
59 	mnSize		( rProp.mnSize ),
60 	mnTextEnc	( rProp.mnTextEnc ),
61 	mpBuf		( new sal_uInt8[ mnSize ] )
62 {
63 	memcpy( (void*)mpBuf, (void*)rProp.mpBuf, mnSize );
64 };
65 
operator =(const PropEntry & rPropEntry)66 const PropEntry& PropEntry::operator=(const PropEntry& rPropEntry)
67 {
68 	if ( this != &rPropEntry )
69 	{
70 		delete[] mpBuf;
71 		mnId = rPropEntry.mnId;
72 		mnSize = rPropEntry.mnSize;
73 		mnTextEnc = rPropEntry.mnTextEnc;
74 		mpBuf = new sal_uInt8[ mnSize ];
75 		memcpy( (void*)mpBuf, (void*)rPropEntry.mpBuf, mnSize );
76 	}
77 	return *this;
78 }
79 
80 //	-----------------------------------------------------------------------
81 
Clear()82 void PropItem::Clear()
83 {
84 	Seek( STREAM_SEEK_TO_BEGIN );
85 	delete[] (sal_uInt8*)SwitchBuffer();
86 }
87 
88 //	-----------------------------------------------------------------------
89 
lcl_getMaxSafeStrLen(sal_uInt32 nSize)90 static xub_StrLen lcl_getMaxSafeStrLen(sal_uInt32 nSize)
91 {
92 	nSize -= 1; //Drop NULL terminator
93 
94 	//If it won't fit in a string, clip it to the max size that does
95     if (nSize > STRING_MAXLEN)
96 		nSize = STRING_MAXLEN;
97 
98 	return static_cast< xub_StrLen >( nSize );
99 }
100 
Read(String & rString,sal_uInt32 nStringType,sal_Bool bAlign)101 sal_Bool PropItem::Read( String& rString, sal_uInt32 nStringType, sal_Bool bAlign )
102 {
103 	sal_uInt32	i, nItemSize, nType, nItemPos;
104 	sal_Bool	bRetValue = sal_False;
105 
106 	nItemPos = Tell();
107 
108 	if ( nStringType == VT_EMPTY )
109 		*this >> nType;
110 	else
111 		nType = nStringType & VT_TYPEMASK;
112 
113 	*this >> nItemSize;
114 
115 	switch( nType )
116 	{
117 		case VT_LPSTR :
118 		{
119 			if ( nItemSize )
120 			{
121 				try
122 				{
123 					sal_Char* pString = new sal_Char[ nItemSize ];
124 					if ( mnTextEnc == RTL_TEXTENCODING_UCS2 )
125 					{
126 						nItemSize >>= 1;
127 						if ( nItemSize > 1 )
128 						{
129 							sal_Unicode* pWString = (sal_Unicode*)pString;
130 							for ( i = 0; i < nItemSize; i++ )
131 								*this >> pWString[ i ];
132 							rString = String( pWString, lcl_getMaxSafeStrLen(nItemSize) );
133 						}
134 						else
135 							rString = String();
136 						bRetValue = sal_True;
137 					}
138 					else
139 					{
140 						SvMemoryStream::Read( pString, nItemSize );
141 						if ( pString[ nItemSize - 1 ] == 0 )
142 						{
143 							if ( nItemSize > 1 )
144 								rString = String( ByteString( pString ), mnTextEnc );
145 							else
146 								rString = String();
147 							bRetValue = sal_True;
148 						}
149 					}
150 					delete[] pString;
151 				}
152 				catch( const std::bad_alloc& )
153 				{
154 					DBG_ERROR( "sd PropItem::Read bad alloc" );
155 				}
156 			}
157 			if ( bAlign )
158 				SeekRel( ( 4 - ( nItemSize & 3 ) ) & 3 );		// dword align
159 		}
160 		break;
161 
162 		case VT_LPWSTR :
163 		{
164 			if ( nItemSize )
165 			{
166 				try
167 				{
168 					sal_Unicode* pString = new sal_Unicode[ nItemSize ];
169 					for ( i = 0; i < nItemSize; i++ )
170 						*this >> pString[ i ];
171 					if ( pString[ i - 1 ] == 0 )
172 					{
173 						if ( (sal_uInt16)nItemSize > 1 )
174 							rString = String( pString, lcl_getMaxSafeStrLen(nItemSize) );
175 						else
176 							rString = String();
177 						bRetValue = sal_True;
178 					}
179 					delete[] pString;
180 				}
181 				catch( const std::bad_alloc& )
182 				{
183 					DBG_ERROR( "sd PropItem::Read bad alloc" );
184 				}
185 			}
186 			if ( bAlign && ( nItemSize & 1 ) )
187 				SeekRel( 2 );							// dword align
188 		}
189 		break;
190 	}
191 	if ( !bRetValue )
192 		Seek( nItemPos );
193 	return bRetValue;
194 }
195 
196 //	-----------------------------------------------------------------------
197 
operator =(PropItem & rPropItem)198 PropItem& PropItem::operator=( PropItem& rPropItem )
199 {
200 	if ( this != &rPropItem )
201 	{
202 		Seek( STREAM_SEEK_TO_BEGIN );
203 		delete[] (sal_uInt8*)SwitchBuffer();
204 
205 		mnTextEnc = rPropItem.mnTextEnc;
206 		sal_uInt32 nItemPos = rPropItem.Tell();
207 		rPropItem.Seek( STREAM_SEEK_TO_END );
208 		SvMemoryStream::Write( rPropItem.GetData(), rPropItem.Tell() );
209 		rPropItem.Seek( nItemPos );
210 	}
211 	return *this;
212 }
213 
214 //	-----------------------------------------------------------------------
215 
216 struct Dict
217 {
218 	sal_uInt32	mnId;
219 	String		aString;
220 
DictDict221 			Dict( sal_uInt32 nId, String rString ) { mnId = nId; aString = rString; };
222 };
223 
224 //	-----------------------------------------------------------------------
225 
~Dictionary()226 Dictionary::~Dictionary()
227 {
228 	for ( void* pPtr = First(); pPtr; pPtr = Next() )
229 		delete (Dict*)pPtr;
230 }
231 
232 //	-----------------------------------------------------------------------
233 
AddProperty(sal_uInt32 nId,const String & rString)234 void Dictionary::AddProperty( sal_uInt32 nId, const String& rString )
235 {
236 	if ( rString.Len() )		// eindeutige namen bei properties
237 	{
238 		// pruefen, ob es die Propertybeschreibung in der Dictionary schon gibt
239 		for ( Dict* pDict = (Dict*)First(); pDict; pDict = (Dict*)Next() )
240 		{
241 			if ( pDict->mnId == nId )
242 			{
243 				pDict->aString = rString;
244 				return;
245 			}
246 		}
247 		Insert( new Dict( nId, rString ), LIST_APPEND );
248 	}
249 }
250 
251 //	-----------------------------------------------------------------------
252 
GetProperty(const String & rString)253 sal_uInt32 Dictionary::GetProperty( const String& rString )
254 {
255 	for ( Dict* pDict = (Dict*)First(); pDict; pDict = (Dict*)Next() )
256 	{
257 		if ( pDict->aString == rString )
258 			return pDict->mnId;
259 	}
260 	return 0;
261 }
262 
263 //	-----------------------------------------------------------------------
264 
operator =(Dictionary & rDictionary)265 Dictionary& Dictionary::operator=( Dictionary& rDictionary )
266 {
267 	void* pPtr;
268 
269 	if ( this != &rDictionary )
270 	{
271 		for ( pPtr = First(); pPtr; pPtr = Next() )
272 			delete (Dict*)pPtr;
273 
274 		for ( pPtr = rDictionary.First(); pPtr; pPtr = rDictionary.Next() )
275 			Insert( new Dict( ((Dict*)pPtr)->mnId, ((Dict*)pPtr)->aString ), LIST_APPEND );
276 	}
277 	return *this;
278 }
279 
280 //	-----------------------------------------------------------------------
281 
Section(Section & rSection)282 Section::Section( Section& rSection )
283 : List()
284 {
285 	mnTextEnc = rSection.mnTextEnc;
286 	for ( int i = 0; i < 16; i++ )
287 		aFMTID[ i ] = rSection.aFMTID[ i ];
288 	for ( PropEntry* pProp = (PropEntry*)rSection.First(); pProp; pProp = (PropEntry*)rSection.Next() )
289 		Insert( new PropEntry( *pProp ), LIST_APPEND );
290 }
291 
292 //	-----------------------------------------------------------------------
293 
Section(const sal_uInt8 * pFMTID)294 Section::Section( const sal_uInt8* pFMTID )
295 {
296 	mnTextEnc = RTL_TEXTENCODING_MS_1252;
297 	for ( int i = 0; i < 16; i++ )
298 		aFMTID[ i ] = pFMTID[ i ];
299 }
300 
301 //	-----------------------------------------------------------------------
302 
GetProperty(sal_uInt32 nId,PropItem & rPropItem)303 sal_Bool Section::GetProperty( sal_uInt32 nId, PropItem& rPropItem )
304 {
305 	PropEntry* pProp;
306 	if ( nId )
307 	{
308 		for ( pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() )
309 		{
310 			if ( pProp->mnId == nId )
311 				break;
312 		}
313 		if ( pProp )
314 		{
315 			rPropItem.Clear();
316 			rPropItem.SetTextEncoding( mnTextEnc );
317 			rPropItem.Write( pProp->mpBuf, pProp->mnSize );
318 			rPropItem.Seek( STREAM_SEEK_TO_BEGIN );
319 			return sal_True;
320 		}
321 	}
322 	return sal_False;
323 }
324 
325 //	-----------------------------------------------------------------------
326 
AddProperty(sal_uInt32 nId,const sal_uInt8 * pBuf,sal_uInt32 nBufSize)327 void Section::AddProperty( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize )
328 {
329 	// kleiner id check
330 
331 	if ( !nId )
332 		return;
333 	if ( nId == 0xffffffff )
334 		nId = 0;
335 
336 	// keine doppelten PropId's zulassen, sortieren
337 	for ( sal_uInt32 i = 0; i < Count(); i++ )
338 	{
339 		PropEntry* pPropEntry = (PropEntry*)GetObject( i );
340 		if ( pPropEntry->mnId == nId )
341 			delete (PropEntry*)Replace( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ), i );
342 		else if ( pPropEntry->mnId > nId )
343 			Insert( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ), i );
344 		else
345 			continue;
346 		return;
347 	}
348 	Insert( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ), LIST_APPEND );
349 }
350 
351 //	-----------------------------------------------------------------------
352 
GetDictionary(Dictionary & rDict)353 sal_Bool Section::GetDictionary( Dictionary& rDict )
354 {
355 	sal_Bool bRetValue = sal_False;
356 
357 	Dictionary aDict;
358 	PropEntry* pProp;
359 
360 	for ( pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() )
361 	{
362 		if ( pProp->mnId == 0 )
363 			break;
364 	}
365 	if ( pProp )
366 	{
367 		sal_uInt32 nDictCount, nId, nSize, nPos;
368 		SvMemoryStream aStream( (sal_Int8*)pProp->mpBuf, pProp->mnSize, STREAM_READ );
369 		aStream.Seek( STREAM_SEEK_TO_BEGIN );
370 		aStream >> nDictCount;
371 		for ( sal_uInt32 i = 0; i < nDictCount; i++ )
372 		{
373 			aStream >> nId >> nSize;
374 			if ( nSize )
375 			{
376 				String aString;
377 				nPos = aStream.Tell();
378 				try
379 				{
380 					sal_Char* pString = new sal_Char[ nSize ];
381 					aStream.Read( pString, nSize );
382 					if ( mnTextEnc == RTL_TEXTENCODING_UCS2 )
383 					{
384 						nSize >>= 1;
385 						aStream.Seek( nPos );
386 						sal_Unicode* pWString = (sal_Unicode*)pString;
387 						for ( i = 0; i < nSize; i++ )
388 							aStream >> pWString[ i ];
389 						aString = String( pWString, lcl_getMaxSafeStrLen(nSize) );
390 					}
391 					else
392 						aString = String( ByteString( pString, lcl_getMaxSafeStrLen(nSize) ), mnTextEnc );
393 					delete[] pString;
394 				}
395 				catch( const std::bad_alloc& )
396 				{
397 					DBG_ERROR( "sd Section::GetDictionary bad alloc" );
398 				}
399 				if ( !aString.Len() )
400 					break;
401 				aDict.AddProperty( nId, aString );
402 			}
403 			bRetValue = sal_True;
404 		}
405 	}
406 	rDict = aDict;
407 	return bRetValue;
408 }
409 
410 //	-----------------------------------------------------------------------
411 
~Section()412 Section::~Section()
413 {
414 	for ( PropEntry* pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() )
415 		delete pProp;
416 }
417 
418 //	-----------------------------------------------------------------------
419 
Read(SvStorageStream * pStrm)420 void Section::Read( SvStorageStream *pStrm )
421 {
422 	sal_uInt32 i, nSecOfs, nSecSize, nPropCount, nPropId, nPropOfs, nPropType, nPropSize, nCurrent, nVectorCount, nTemp, nStrmSize;
423 	nSecOfs = pStrm->Tell();
424 
425 	pStrm->Seek( STREAM_SEEK_TO_END );
426 	nStrmSize = pStrm->Tell();
427 	pStrm->Seek( nSecOfs );
428 
429 	mnTextEnc = RTL_TEXTENCODING_MS_1252;
430 	*pStrm >> nSecSize >> nPropCount;
431 	while( nPropCount-- && ( pStrm->GetError() == ERRCODE_NONE ) )
432 	{
433 		*pStrm >> nPropId >> nPropOfs;
434 		nCurrent = pStrm->Tell();
435 		pStrm->Seek( nPropOfs + nSecOfs );
436 		if ( nPropId )					// dictionary wird nicht eingelesen
437 		{
438 
439 			*pStrm >> nPropType;
440 
441 			nPropSize = 4;
442 
443 			if ( nPropType & VT_VECTOR )
444 			{
445 				*pStrm >> nVectorCount;
446 				nPropType &=~VT_VECTOR;
447 				nPropSize += 4;
448 			}
449 			else
450 				nVectorCount = 1;
451 
452 
453 			sal_Bool bVariant = ( nPropType == VT_VARIANT );
454 
455 			for ( i = 0; nPropSize && ( i < nVectorCount ); i++ )
456 			{
457 				if ( bVariant )
458 				{
459 					*pStrm >> nPropType;
460 					nPropSize += 4;
461 				}
462 				switch( nPropType )
463 				{
464 					case VT_UI1 :
465 						nPropSize++;
466 					break;
467 
468 					case VT_I2 :
469 					case VT_UI2 :
470 					case VT_BOOL :
471 						nPropSize += 2;
472 					break;
473 
474 					case VT_I4 :
475 					case VT_R4 :
476 					case VT_UI4 :
477 					case VT_ERROR :
478 						nPropSize += 4;
479 					break;
480 
481 					case VT_I8 :
482 					case VT_R8 :
483 					case VT_CY :
484 					case VT_UI8 :
485 					case VT_DATE :
486 					case VT_FILETIME :
487 						nPropSize += 8;
488 					break;
489 
490 					case VT_BSTR :
491 						*pStrm >> nTemp;
492 						nPropSize += ( nTemp + 4 );
493 					break;
494 
495 					case VT_LPSTR :
496 						*pStrm >> nTemp;
497 						nPropSize += ( nTemp + 4 );
498 					break;
499 
500 					case VT_LPWSTR :
501 						*pStrm >> nTemp;
502 						nPropSize += ( nTemp << 1 ) + 4;
503 					break;
504 
505 					case VT_BLOB_OBJECT :
506 					case VT_BLOB :
507 					case VT_CF :
508 						*pStrm >> nTemp;
509 						nPropSize += ( nTemp + 4 );
510 					break;
511 
512 					case VT_CLSID :
513 					case VT_STREAM :
514 					case VT_STORAGE :
515 					case VT_STREAMED_OBJECT :
516 					case VT_STORED_OBJECT :
517 					case VT_VARIANT :
518 					case VT_VECTOR :
519 					default :
520 						nPropSize = 0;
521 				}
522 				if ( nPropSize )
523 				{
524 					if ( ( nVectorCount - i ) > 1 )
525 						pStrm->Seek( nPropOfs + nSecOfs + nPropSize );
526 				}
527 				else
528 					break;
529 			}
530 			if ( nPropSize )
531 			{
532 				if ( nPropSize > nStrmSize )
533 				{
534 					nPropCount = 0;
535 					break;
536 				}
537 				pStrm->Seek( nPropOfs + nSecOfs );
538 				sal_uInt8* pBuf = new sal_uInt8[ nPropSize ];
539 				pStrm->Read( pBuf, nPropSize );
540 				AddProperty( nPropId, pBuf, nPropSize );
541 				delete[] pBuf;
542 			}
543 			if ( nPropId == 1 )
544             {
545 				PropItem aPropItem;
546 				if ( GetProperty( 1, aPropItem ) )
547 				{
548 					sal_uInt16 nCodePage;
549 	                aPropItem >> nPropType;
550 		            if ( nPropType == VT_I2 )
551 					{
552 						aPropItem >> nCodePage;
553 
554 						if ( nCodePage == 1200 )
555 						{
556 							mnTextEnc = RTL_TEXTENCODING_UCS2;
557 						}
558 						else
559 						{
560 							mnTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage );
561 							if ( mnTextEnc == RTL_TEXTENCODING_DONTKNOW )
562 								mnTextEnc = RTL_TEXTENCODING_MS_1252;
563 						}
564 					}
565 					else
566 					{
567 						mnTextEnc = RTL_TEXTENCODING_MS_1252;
568 					}
569 				}
570 			}
571 		}
572 		else
573 		{
574 			sal_uInt32 nDictCount, nSize;
575 			*pStrm >> nDictCount;
576 			for ( i = 0; i < nDictCount; i++ )
577 			{
578 				*pStrm >> nSize >> nSize;
579 				pStrm->SeekRel( nSize );
580 			}
581 			nSize = pStrm->Tell();
582 			pStrm->Seek( nPropOfs + nSecOfs );
583 			nSize -= pStrm->Tell();
584 			if ( nSize > nStrmSize )
585 			{
586 				nPropCount = 0;
587 				break;
588 			}
589 			sal_uInt8* pBuf = new sal_uInt8[ nSize ];
590 			pStrm->Read( pBuf, nSize );
591 			AddProperty( 0xffffffff, pBuf, nSize );
592 			delete[] pBuf;
593 		}
594 		pStrm->Seek( nCurrent );
595 	}
596 	pStrm->Seek( nSecOfs + nSecSize );
597 }
598 
599 //	-----------------------------------------------------------------------
600 
operator =(Section & rSection)601 Section& Section::operator=( Section& rSection )
602 {
603 	PropEntry* pProp;
604 
605 	if ( this != &rSection )
606 	{
607 		memcpy( (void*)aFMTID, (void*)rSection.aFMTID, 16 );
608 		for ( pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() )
609 			delete pProp;
610 		Clear();
611 		for ( pProp = (PropEntry*)rSection.First(); pProp; pProp = (PropEntry*)rSection.Next() )
612 			Insert( new PropEntry( *pProp ), LIST_APPEND );
613 	}
614 	return *this;
615 }
616 
617 //	-----------------------------------------------------------------------
618 
PropRead(SvStorage & rStorage,const String & rName)619 PropRead::PropRead( SvStorage& rStorage, const String& rName ) :
620 		mbStatus			( sal_False ),
621 		mnByteOrder			( 0xfffe ),
622 		mnFormat			( 0 ),
623 		mnVersionLo			( 4 ),
624 		mnVersionHi			( 2 )
625 {
626 	if ( rStorage.IsStream( rName ) )
627 	{
628         mpSvStream = rStorage.OpenSotStream( rName, STREAM_STD_READ );
629 		if ( mpSvStream )
630 		{
631 			mpSvStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
632 			memset( mApplicationCLSID, 0, 16 );
633 			mbStatus = sal_True;
634 		}
635 	}
636 }
637 
638 //	-----------------------------------------------------------------------
639 
AddSection(Section & rSection)640 void PropRead::AddSection( Section& rSection )
641 {
642 	Insert( new Section( rSection ), LIST_APPEND );
643 }
644 
645 //	-----------------------------------------------------------------------
646 
GetSection(const sal_uInt8 * pFMTID)647 const Section* PropRead::GetSection( const sal_uInt8* pFMTID )
648 {
649 	Section* pSection;
650 
651 	for ( pSection = (Section*)First(); pSection; pSection = (Section*)Next() )
652 	{
653 		if ( memcmp( pSection->GetFMTID(), pFMTID, 16 ) == 0 )
654 			break;
655 	}
656 	return pSection;
657 }
658 
659 //	-----------------------------------------------------------------------
660 
~PropRead()661 PropRead::~PropRead()
662 {
663 	for ( Section* pSection = (Section*)First(); pSection; pSection = (Section*)Next() )
664 		delete pSection;
665 }
666 
667 //	-----------------------------------------------------------------------
668 
Read()669 void PropRead::Read()
670 {
671 	for ( Section* pSection = (Section*)First(); pSection; pSection = (Section*)Next() )
672 		delete pSection;
673 	Clear();
674 	if ( mbStatus )
675 	{
676 		sal_uInt32	nSections;
677 		sal_uInt32	nSectionOfs;
678 		sal_uInt32	nCurrent;
679 		*mpSvStream >> mnByteOrder >> mnFormat >> mnVersionLo >> mnVersionHi;
680 		if ( mnByteOrder == 0xfffe )
681 		{
682 			sal_uInt8*	pSectCLSID = new sal_uInt8[ 16 ];
683 			mpSvStream->Read( mApplicationCLSID, 16 );
684 			*mpSvStream >> nSections;
685 			if ( nSections > 2 )				// sj: PowerPoint documents are containing max 2 sections
686 			{
687 				mbStatus = sal_False;
688 			}
689 			else for ( sal_uInt32 i = 0; i < nSections; i++ )
690 			{
691 				mpSvStream->Read( pSectCLSID, 16 );
692 				*mpSvStream >> nSectionOfs;
693 				nCurrent = mpSvStream->Tell();
694 				mpSvStream->Seek( nSectionOfs );
695 				Section aSection( pSectCLSID );
696 				aSection.Read( mpSvStream );
697 				AddSection( aSection );
698 				mpSvStream->Seek( nCurrent );
699 			}
700 			delete[] pSectCLSID;
701 		}
702 	}
703 }
704 
705 //	-----------------------------------------------------------------------
706 
operator =(PropRead & rPropRead)707 PropRead& PropRead::operator=( PropRead& rPropRead )
708 {
709 	Section* pSection;
710 
711 	if ( this != &rPropRead )
712 	{
713 		mbStatus = rPropRead.mbStatus;
714 		mpSvStream = rPropRead.mpSvStream;
715 
716 		mnByteOrder = rPropRead.mnByteOrder;
717 		mnFormat = rPropRead.mnFormat;
718 		mnVersionLo = rPropRead.mnVersionLo;
719 		mnVersionHi = rPropRead.mnVersionHi;
720 		memcpy( mApplicationCLSID, rPropRead.mApplicationCLSID, 16 );
721 
722 		for ( pSection = (Section*)First(); pSection; pSection = (Section*)Next() )
723 			delete pSection;
724 		Clear();
725 		for ( pSection = (Section*)rPropRead.First(); pSection; pSection = (Section*)rPropRead.Next() )
726 			Insert( new Section( *pSection ), LIST_APPEND );
727 	}
728 	return *this;
729 }
730