bump product version to 4.1.6.2
[LibreOffice.git] / sd / source / filter / ppt / propread.cxx
blob38e2d7a87e3fe692a4a0af8664bed98a0fc5dbdc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <propread.hxx>
21 #include "rtl/tencinfo.h"
22 #include "rtl/textenc.h"
24 PropEntry::PropEntry( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize, sal_uInt16 nTextEnc ) :
25 mnId ( nId ),
26 mnSize ( nBufSize ),
27 mnTextEnc ( nTextEnc ),
28 mpBuf ( new sal_uInt8[ nBufSize ] )
30 memcpy( (void*)mpBuf, (void*)pBuf, nBufSize );
33 PropEntry::PropEntry( const PropEntry& rProp ) :
34 mnId ( rProp.mnId ),
35 mnSize ( rProp.mnSize ),
36 mnTextEnc ( rProp.mnTextEnc ),
37 mpBuf ( new sal_uInt8[ mnSize ] )
39 memcpy( (void*)mpBuf, (void*)rProp.mpBuf, mnSize );
42 PropEntry& PropEntry::operator=(const PropEntry& rPropEntry)
44 if ( this != &rPropEntry )
46 delete[] mpBuf;
47 mnId = rPropEntry.mnId;
48 mnSize = rPropEntry.mnSize;
49 mnTextEnc = rPropEntry.mnTextEnc;
50 mpBuf = new sal_uInt8[ mnSize ];
51 memcpy( (void*)mpBuf, (void*)rPropEntry.mpBuf, mnSize );
53 return *this;
56 // -----------------------------------------------------------------------
58 void PropItem::Clear()
60 Seek( STREAM_SEEK_TO_BEGIN );
61 delete[] (sal_uInt8*)SwitchBuffer();
64 // -----------------------------------------------------------------------
66 static xub_StrLen lcl_getMaxSafeStrLen(sal_uInt32 nSize)
68 nSize -= 1; //Drop NULL terminator
70 //If it won't fit in a string, clip it to the max size that does
71 if (nSize > STRING_MAXLEN)
72 nSize = STRING_MAXLEN;
74 return static_cast< xub_StrLen >( nSize );
77 sal_Bool PropItem::Read( OUString& rString, sal_uInt32 nStringType, sal_Bool bAlign )
79 sal_uInt32 i, nItemSize, nType, nItemPos;
80 sal_Bool bRetValue = sal_False;
82 nItemPos = Tell();
84 if ( nStringType == VT_EMPTY )
85 *this >> nType;
86 else
87 nType = nStringType & VT_TYPEMASK;
89 *this >> nItemSize;
91 switch( nType )
93 case VT_LPSTR :
95 if ( nItemSize )
97 try
99 sal_Char* pString = new sal_Char[ nItemSize ];
100 if ( mnTextEnc == RTL_TEXTENCODING_UCS2 )
102 nItemSize >>= 1;
103 if ( nItemSize > 1 )
105 sal_Unicode* pWString = (sal_Unicode*)pString;
106 for ( i = 0; i < nItemSize; i++ )
107 *this >> pWString[ i ];
108 rString = OUString(pWString, lcl_getMaxSafeStrLen(nItemSize));
110 else
111 rString = OUString();
112 bRetValue = sal_True;
114 else
116 SvMemoryStream::Read( pString, nItemSize );
117 if ( pString[ nItemSize - 1 ] == 0 )
119 if ( nItemSize > 1 )
120 rString = OUString(pString, rtl_str_getLength(pString), mnTextEnc);
121 else
122 rString = OUString();
123 bRetValue = sal_True;
126 delete[] pString;
128 catch( const std::bad_alloc& )
130 OSL_FAIL( "sd PropItem::Read bad alloc" );
133 if ( bAlign )
134 SeekRel( ( 4 - ( nItemSize & 3 ) ) & 3 ); // dword align
136 break;
138 case VT_LPWSTR :
140 if ( nItemSize )
144 sal_Unicode* pString = new sal_Unicode[ nItemSize ];
145 for ( i = 0; i < nItemSize; i++ )
146 *this >> pString[ i ];
147 if ( pString[ i - 1 ] == 0 )
149 if ( (sal_uInt16)nItemSize > 1 )
150 rString = OUString(pString, lcl_getMaxSafeStrLen(nItemSize));
151 else
152 rString = OUString();
153 bRetValue = sal_True;
155 delete[] pString;
157 catch( const std::bad_alloc& )
159 OSL_FAIL( "sd PropItem::Read bad alloc" );
162 if ( bAlign && ( nItemSize & 1 ) )
163 SeekRel( 2 ); // dword align
165 break;
167 if ( !bRetValue )
168 Seek( nItemPos );
169 return bRetValue;
172 // -----------------------------------------------------------------------
174 PropItem& PropItem::operator=( PropItem& rPropItem )
176 if ( this != &rPropItem )
178 Seek( STREAM_SEEK_TO_BEGIN );
179 delete[] (sal_uInt8*)SwitchBuffer();
181 mnTextEnc = rPropItem.mnTextEnc;
182 sal_uInt32 nItemPos = rPropItem.Tell();
183 rPropItem.Seek( STREAM_SEEK_TO_END );
184 SvMemoryStream::Write( rPropItem.GetData(), rPropItem.Tell() );
185 rPropItem.Seek( nItemPos );
187 return *this;
190 // -----------------------------------------------------------------------
192 Section::Section( const Section& rSection )
193 : mnTextEnc(rSection.mnTextEnc),
194 maEntries(rSection.maEntries.clone())
196 for ( int i = 0; i < 16; i++ )
197 aFMTID[ i ] = rSection.aFMTID[ i ];
200 // -----------------------------------------------------------------------
202 Section::Section( const sal_uInt8* pFMTID )
204 mnTextEnc = RTL_TEXTENCODING_MS_1252;
205 for ( int i = 0; i < 16; i++ )
206 aFMTID[ i ] = pFMTID[ i ];
209 // -----------------------------------------------------------------------
211 sal_Bool Section::GetProperty( sal_uInt32 nId, PropItem& rPropItem )
213 if ( nId )
215 boost::ptr_vector<PropEntry>::const_iterator iter;
216 for (iter = maEntries.begin(); iter != maEntries.end(); ++iter)
218 if (iter->mnId == nId)
219 break;
222 if (iter != maEntries.end())
224 rPropItem.Clear();
225 rPropItem.SetTextEncoding( mnTextEnc );
226 rPropItem.Write( iter->mpBuf,iter->mnSize );
227 rPropItem.Seek( STREAM_SEEK_TO_BEGIN );
228 return sal_True;
231 return sal_False;
234 // -----------------------------------------------------------------------
236 void Section::AddProperty( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize )
238 // just a simple id check
240 if ( !nId )
241 return;
242 if ( nId == 0xffffffff )
243 nId = 0;
245 // do not allow same PropId's, sort
246 boost::ptr_vector<PropEntry>::iterator iter;
247 for ( iter = maEntries.begin(); iter != maEntries.end(); ++iter )
249 if ( iter->mnId == nId )
250 maEntries.replace( iter, new PropEntry( nId, pBuf, nBufSize, mnTextEnc ));
251 else if ( iter->mnId > nId )
252 maEntries.insert( iter, new PropEntry( nId, pBuf, nBufSize, mnTextEnc ));
253 else
254 continue;
255 return;
258 maEntries.push_back( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ) );
261 // -----------------------------------------------------------------------
263 sal_Bool Section::GetDictionary( Dictionary& rDict )
265 sal_Bool bRetValue = sal_False;
267 boost::ptr_vector<PropEntry>::iterator iter;
268 for (iter = maEntries.begin(); iter != maEntries.end(); ++iter)
270 if ( iter->mnId == 0 )
271 break;
274 if ( iter != maEntries.end() )
276 sal_uInt32 nDictCount, nId, nSize, nPos;
277 SvMemoryStream aStream( (sal_Int8*)iter->mpBuf, iter->mnSize, STREAM_READ );
278 aStream.Seek( STREAM_SEEK_TO_BEGIN );
279 aStream >> nDictCount;
280 for ( sal_uInt32 i = 0; i < nDictCount; i++ )
282 aStream >> nId >> nSize;
283 if ( nSize )
285 String aString;
286 nPos = aStream.Tell();
289 sal_Char* pString = new sal_Char[ nSize ];
290 aStream.Read( pString, nSize );
291 if ( mnTextEnc == RTL_TEXTENCODING_UCS2 )
293 nSize >>= 1;
294 aStream.Seek( nPos );
295 sal_Unicode* pWString = (sal_Unicode*)pString;
296 for ( i = 0; i < nSize; i++ )
297 aStream >> pWString[ i ];
298 aString = OUString(pWString, lcl_getMaxSafeStrLen(nSize));
300 else
301 aString = OUString(pString, lcl_getMaxSafeStrLen(nSize), mnTextEnc);
302 delete[] pString;
304 catch( const std::bad_alloc& )
306 OSL_FAIL( "sd Section::GetDictionary bad alloc" );
308 if ( !aString.Len() )
309 break;
310 rDict.insert( std::make_pair(aString,nId) );
312 bRetValue = sal_True;
315 return bRetValue;
318 // -----------------------------------------------------------------------
320 void Section::Read( SvStorageStream *pStrm )
322 sal_uInt32 i, nSecOfs, nSecSize, nPropCount, nPropId, nPropOfs, nPropType, nPropSize, nCurrent, nVectorCount, nTemp, nStrmSize;
323 nSecOfs = pStrm->Tell();
325 pStrm->Seek( STREAM_SEEK_TO_END );
326 nStrmSize = pStrm->Tell();
327 pStrm->Seek( nSecOfs );
329 mnTextEnc = RTL_TEXTENCODING_MS_1252;
330 *pStrm >> nSecSize >> nPropCount;
331 while( nPropCount-- && ( pStrm->GetError() == ERRCODE_NONE ) )
333 *pStrm >> nPropId >> nPropOfs;
334 nCurrent = pStrm->Tell();
335 pStrm->Seek( nPropOfs + nSecOfs );
336 if ( nPropId ) // do not read dictionary
339 *pStrm >> nPropType;
341 nPropSize = 4;
343 if ( nPropType & VT_VECTOR )
345 *pStrm >> nVectorCount;
346 nPropType &=~VT_VECTOR;
347 nPropSize += 4;
349 else
350 nVectorCount = 1;
353 sal_Bool bVariant = ( nPropType == VT_VARIANT );
355 for ( i = 0; nPropSize && ( i < nVectorCount ); i++ )
357 if ( bVariant )
359 *pStrm >> nPropType;
360 nPropSize += 4;
362 switch( nPropType )
364 case VT_UI1 :
365 nPropSize++;
366 break;
368 case VT_I2 :
369 case VT_UI2 :
370 case VT_BOOL :
371 nPropSize += 2;
372 break;
374 case VT_I4 :
375 case VT_R4 :
376 case VT_UI4 :
377 case VT_ERROR :
378 nPropSize += 4;
379 break;
381 case VT_I8 :
382 case VT_R8 :
383 case VT_CY :
384 case VT_UI8 :
385 case VT_DATE :
386 case VT_FILETIME :
387 nPropSize += 8;
388 break;
390 case VT_BSTR :
391 *pStrm >> nTemp;
392 nPropSize += ( nTemp + 4 );
393 break;
395 case VT_LPSTR :
396 *pStrm >> nTemp;
397 nPropSize += ( nTemp + 4 );
398 break;
400 case VT_LPWSTR :
402 *pStrm >> nTemp;
403 // looks like these are aligned to 4 bytes
404 sal_uInt32 nLength = nPropOfs + nSecOfs + nPropSize + ( nTemp << 1 ) + 4;
405 nPropSize += ( nTemp << 1 ) + 4 + (nLength % 4);
407 break;
409 case VT_BLOB_OBJECT :
410 case VT_BLOB :
411 case VT_CF :
412 *pStrm >> nTemp;
413 nPropSize += ( nTemp + 4 );
414 break;
416 case VT_CLSID :
417 case VT_STREAM :
418 case VT_STORAGE :
419 case VT_STREAMED_OBJECT :
420 case VT_STORED_OBJECT :
421 case VT_VARIANT :
422 case VT_VECTOR :
423 default :
424 nPropSize = 0;
426 if ( nPropSize )
428 if ( ( nVectorCount - i ) > 1 )
429 pStrm->Seek( nPropOfs + nSecOfs + nPropSize );
431 else
432 break;
434 if ( nPropSize )
436 if ( nPropSize > nStrmSize )
438 nPropCount = 0;
439 break;
441 pStrm->Seek( nPropOfs + nSecOfs );
442 // make sure we don't overflow the section size
443 if( nPropSize > nSecSize - nSecOfs )
444 nPropSize = nSecSize - nSecOfs;
445 sal_uInt8* pBuf = new sal_uInt8[ nPropSize ];
446 pStrm->Read( pBuf, nPropSize );
447 AddProperty( nPropId, pBuf, nPropSize );
448 delete[] pBuf;
450 if ( nPropId == 1 )
452 PropItem aPropItem;
453 if ( GetProperty( 1, aPropItem ) )
455 sal_uInt16 nCodePage;
456 aPropItem >> nPropType;
457 if ( nPropType == VT_I2 )
459 aPropItem >> nCodePage;
461 if ( nCodePage == 1200 )
463 mnTextEnc = RTL_TEXTENCODING_UCS2;
465 else
467 mnTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage );
468 if ( mnTextEnc == RTL_TEXTENCODING_DONTKNOW )
469 mnTextEnc = RTL_TEXTENCODING_MS_1252;
472 else
474 mnTextEnc = RTL_TEXTENCODING_MS_1252;
479 else
481 sal_uInt32 nDictCount, nSize;
482 *pStrm >> nDictCount;
483 for ( i = 0; i < nDictCount; i++ )
485 *pStrm >> nSize >> nSize;
486 pStrm->SeekRel( nSize );
488 nSize = pStrm->Tell();
489 pStrm->Seek( nPropOfs + nSecOfs );
490 nSize -= pStrm->Tell();
491 if ( nSize > nStrmSize )
493 nPropCount = 0;
494 break;
496 sal_uInt8* pBuf = new sal_uInt8[ nSize ];
497 pStrm->Read( pBuf, nSize );
498 AddProperty( 0xffffffff, pBuf, nSize );
499 delete[] pBuf;
501 pStrm->Seek( nCurrent );
503 pStrm->Seek( nSecOfs + nSecSize );
506 // -----------------------------------------------------------------------
508 Section& Section::operator=( const Section& rSection )
510 if ( this != &rSection )
512 memcpy( (void*)aFMTID, (void*)rSection.aFMTID, 16 );
514 maEntries = rSection.maEntries.clone();
516 return *this;
519 // -----------------------------------------------------------------------
521 PropRead::PropRead( SvStorage& rStorage, const String& rName ) :
522 mbStatus ( sal_False ),
523 mnByteOrder ( 0xfffe ),
524 mnFormat ( 0 ),
525 mnVersionLo ( 4 ),
526 mnVersionHi ( 2 )
528 if ( rStorage.IsStream( rName ) )
530 mpSvStream = rStorage.OpenSotStream( rName, STREAM_STD_READ );
531 if ( mpSvStream )
533 mpSvStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
534 memset( mApplicationCLSID, 0, 16 );
535 mbStatus = sal_True;
540 // -----------------------------------------------------------------------
542 void PropRead::AddSection( Section& rSection )
544 maSections.push_back( new Section( rSection ) );
547 // -----------------------------------------------------------------------
549 const Section* PropRead::GetSection( const sal_uInt8* pFMTID )
551 boost::ptr_vector<Section>::iterator it;
552 for ( it = maSections.begin(); it != maSections.end(); ++it)
554 if ( memcmp( it->GetFMTID(), pFMTID, 16 ) == 0 )
555 return &(*it);
557 return NULL;
560 // -----------------------------------------------------------------------
562 void PropRead::Read()
564 maSections.clear();
566 if ( mbStatus )
568 sal_uInt32 nSections;
569 sal_uInt32 nSectionOfs;
570 sal_uInt32 nCurrent;
571 *mpSvStream >> mnByteOrder >> mnFormat >> mnVersionLo >> mnVersionHi;
572 if ( mnByteOrder == 0xfffe )
574 sal_uInt8* pSectCLSID = new sal_uInt8[ 16 ];
575 mpSvStream->Read( mApplicationCLSID, 16 );
576 *mpSvStream >> nSections;
577 if ( nSections > 2 ) // sj: PowerPoint documents are containing max 2 sections
579 mbStatus = sal_False;
581 else for ( sal_uInt32 i = 0; i < nSections; i++ )
583 mpSvStream->Read( pSectCLSID, 16 );
584 *mpSvStream >> nSectionOfs;
585 nCurrent = mpSvStream->Tell();
586 mpSvStream->Seek( nSectionOfs );
587 Section aSection( pSectCLSID );
588 aSection.Read( mpSvStream );
589 AddSection( aSection );
590 mpSvStream->Seek( nCurrent );
592 delete[] pSectCLSID;
597 // -----------------------------------------------------------------------
599 PropRead& PropRead::operator=( const PropRead& rPropRead )
601 if ( this != &rPropRead )
603 mbStatus = rPropRead.mbStatus;
604 mpSvStream = rPropRead.mpSvStream;
606 mnByteOrder = rPropRead.mnByteOrder;
607 mnFormat = rPropRead.mnFormat;
608 mnVersionLo = rPropRead.mnVersionLo;
609 mnVersionHi = rPropRead.mnVersionHi;
610 memcpy( mApplicationCLSID, rPropRead.mApplicationCLSID, 16 );
612 maSections = rPropRead.maSections.clone();
614 return *this;
617 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */