diff options
Diffstat (limited to 'sd/source/filter/ppt/propread.cxx')
-rwxr-xr-x | sd/source/filter/ppt/propread.cxx | 733 |
1 files changed, 733 insertions, 0 deletions
diff --git a/sd/source/filter/ppt/propread.cxx b/sd/source/filter/ppt/propread.cxx new file mode 100755 index 000000000000..ff1250bdf090 --- /dev/null +++ b/sd/source/filter/ppt/propread.cxx @@ -0,0 +1,733 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <propread.hxx> +#include <tools/bigint.hxx> +#include "tools/debug.hxx" +#include "rtl/tencinfo.h" +#include "rtl/textenc.h" + +// ------------------------------------------------------------------------ + +struct PropEntry +{ + sal_uInt32 mnId; + sal_uInt32 mnSize; + sal_uInt16 mnTextEnc; + sal_uInt8* mpBuf; + + PropEntry( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize, sal_uInt16 nTextEnc ); + PropEntry( const PropEntry& rProp ); + ~PropEntry() { delete[] mpBuf; } ; + + const PropEntry& operator=(const PropEntry& rPropEntry); +}; + +PropEntry::PropEntry( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize, sal_uInt16 nTextEnc ) : + mnId ( nId ), + mnSize ( nBufSize ), + mnTextEnc ( nTextEnc ), + mpBuf ( new sal_uInt8[ nBufSize ] ) +{ + memcpy( (void*)mpBuf, (void*)pBuf, nBufSize ); +}; + +PropEntry::PropEntry( const PropEntry& rProp ) : + mnId ( rProp.mnId ), + mnSize ( rProp.mnSize ), + mnTextEnc ( rProp.mnTextEnc ), + mpBuf ( new sal_uInt8[ mnSize ] ) +{ + memcpy( (void*)mpBuf, (void*)rProp.mpBuf, mnSize ); +}; + +const PropEntry& PropEntry::operator=(const PropEntry& rPropEntry) +{ + if ( this != &rPropEntry ) + { + delete[] mpBuf; + mnId = rPropEntry.mnId; + mnSize = rPropEntry.mnSize; + mnTextEnc = rPropEntry.mnTextEnc; + mpBuf = new sal_uInt8[ mnSize ]; + memcpy( (void*)mpBuf, (void*)rPropEntry.mpBuf, mnSize ); + } + return *this; +} + +// ----------------------------------------------------------------------- + +void PropItem::Clear() +{ + Seek( STREAM_SEEK_TO_BEGIN ); + delete[] (sal_uInt8*)SwitchBuffer(); +} + +// ----------------------------------------------------------------------- + +static xub_StrLen lcl_getMaxSafeStrLen(sal_uInt32 nSize) +{ + nSize -= 1; //Drop NULL terminator + + //If it won't fit in a string, clip it to the max size that does + if (nSize > STRING_MAXLEN) + nSize = STRING_MAXLEN; + + return nSize; +} + +BOOL PropItem::Read( String& rString, sal_uInt32 nStringType, sal_Bool bAlign ) +{ + sal_uInt32 i, nItemSize, nType, nItemPos; + sal_Bool bRetValue = sal_False; + + nItemPos = Tell(); + + if ( nStringType == VT_EMPTY ) + *this >> nType; + else + nType = nStringType & VT_TYPEMASK; + + *this >> nItemSize; + + switch( nType ) + { + case VT_LPSTR : + { + if ( nItemSize ) + { + try + { + sal_Char* pString = new sal_Char[ nItemSize ]; + if ( mnTextEnc == RTL_TEXTENCODING_UCS2 ) + { + nItemSize >>= 1; + if ( nItemSize > 1 ) + { + sal_Unicode* pWString = (sal_Unicode*)pString; + for ( i = 0; i < nItemSize; i++ ) + *this >> pWString[ i ]; + rString = String( pWString, lcl_getMaxSafeStrLen(nItemSize) ); + } + else + rString = String(); + bRetValue = sal_True; + } + else + { + SvMemoryStream::Read( pString, nItemSize ); + if ( pString[ nItemSize - 1 ] == 0 ) + { + if ( nItemSize > 1 ) + rString = String( ByteString( pString ), mnTextEnc ); + else + rString = String(); + bRetValue = sal_True; + } + } + delete[] pString; + } + catch( const std::bad_alloc& ) + { + DBG_ERROR( "sd PropItem::Read bad alloc" ); + } + } + if ( bAlign ) + SeekRel( ( 4 - ( nItemSize & 3 ) ) & 3 ); // dword align + } + break; + + case VT_LPWSTR : + { + if ( nItemSize ) + { + try + { + sal_Unicode* pString = new sal_Unicode[ nItemSize ]; + for ( i = 0; i < nItemSize; i++ ) + *this >> pString[ i ]; + if ( pString[ i - 1 ] == 0 ) + { + if ( (sal_uInt16)nItemSize > 1 ) + rString = String( pString, lcl_getMaxSafeStrLen(nItemSize) ); + else + rString = String(); + bRetValue = sal_True; + } + delete[] pString; + } + catch( const std::bad_alloc& ) + { + DBG_ERROR( "sd PropItem::Read bad alloc" ); + } + } + if ( bAlign && ( nItemSize & 1 ) ) + SeekRel( 2 ); // dword align + } + break; + } + if ( !bRetValue ) + Seek( nItemPos ); + return bRetValue; +} + +// ----------------------------------------------------------------------- + +PropItem& PropItem::operator=( PropItem& rPropItem ) +{ + if ( this != &rPropItem ) + { + Seek( STREAM_SEEK_TO_BEGIN ); + delete[] (sal_uInt8*)SwitchBuffer(); + + mnTextEnc = rPropItem.mnTextEnc; + sal_uInt32 nItemPos = rPropItem.Tell(); + rPropItem.Seek( STREAM_SEEK_TO_END ); + SvMemoryStream::Write( rPropItem.GetData(), rPropItem.Tell() ); + rPropItem.Seek( nItemPos ); + } + return *this; +} + +// ----------------------------------------------------------------------- + +struct Dict +{ + sal_uInt32 mnId; + String aString; + + Dict( sal_uInt32 nId, String rString ) { mnId = nId; aString = rString; }; +}; + +// ----------------------------------------------------------------------- + +Dictionary::~Dictionary() +{ + for ( void* pPtr = First(); pPtr; pPtr = Next() ) + delete (Dict*)pPtr; +} + +// ----------------------------------------------------------------------- + +void Dictionary::AddProperty( sal_uInt32 nId, const String& rString ) +{ + if ( rString.Len() ) // eindeutige namen bei properties + { + // pruefen, ob es die Propertybeschreibung in der Dictionary schon gibt + for ( Dict* pDict = (Dict*)First(); pDict; pDict = (Dict*)Next() ) + { + if ( pDict->mnId == nId ) + { + pDict->aString = rString; + return; + } + } + Insert( new Dict( nId, rString ), LIST_APPEND ); + } +} + +// ----------------------------------------------------------------------- + +UINT32 Dictionary::GetProperty( const String& rString ) +{ + for ( Dict* pDict = (Dict*)First(); pDict; pDict = (Dict*)Next() ) + { + if ( pDict->aString == rString ) + return pDict->mnId; + } + return 0; +} + +// ----------------------------------------------------------------------- + +Dictionary& Dictionary::operator=( Dictionary& rDictionary ) +{ + void* pPtr; + + if ( this != &rDictionary ) + { + for ( pPtr = First(); pPtr; pPtr = Next() ) + delete (Dict*)pPtr; + + for ( pPtr = rDictionary.First(); pPtr; pPtr = rDictionary.Next() ) + Insert( new Dict( ((Dict*)pPtr)->mnId, ((Dict*)pPtr)->aString ), LIST_APPEND ); + } + return *this; +} + +// ----------------------------------------------------------------------- + +Section::Section( Section& rSection ) +: List() +{ + mnTextEnc = rSection.mnTextEnc; + for ( int i = 0; i < 16; i++ ) + aFMTID[ i ] = rSection.aFMTID[ i ]; + for ( PropEntry* pProp = (PropEntry*)rSection.First(); pProp; pProp = (PropEntry*)rSection.Next() ) + Insert( new PropEntry( *pProp ), LIST_APPEND ); +} + +// ----------------------------------------------------------------------- + +Section::Section( const sal_uInt8* pFMTID ) +{ + mnTextEnc = RTL_TEXTENCODING_MS_1252; + for ( int i = 0; i < 16; i++ ) + aFMTID[ i ] = pFMTID[ i ]; +} + +// ----------------------------------------------------------------------- + +sal_Bool Section::GetProperty( sal_uInt32 nId, PropItem& rPropItem ) +{ + PropEntry* pProp; + if ( nId ) + { + for ( pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() ) + { + if ( pProp->mnId == nId ) + break; + } + if ( pProp ) + { + rPropItem.Clear(); + rPropItem.SetTextEncoding( mnTextEnc ); + rPropItem.Write( pProp->mpBuf, pProp->mnSize ); + rPropItem.Seek( STREAM_SEEK_TO_BEGIN ); + return sal_True; + } + } + return sal_False; +} + +// ----------------------------------------------------------------------- + +void Section::AddProperty( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize ) +{ + // kleiner id check + + if ( !nId ) + return; + if ( nId == 0xffffffff ) + nId = 0; + + // keine doppelten PropId's zulassen, sortieren + for ( sal_uInt32 i = 0; i < Count(); i++ ) + { + PropEntry* pPropEntry = (PropEntry*)GetObject( i ); + if ( pPropEntry->mnId == nId ) + delete (PropEntry*)Replace( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ), i ); + else if ( pPropEntry->mnId > nId ) + Insert( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ), i ); + else + continue; + return; + } + Insert( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ), LIST_APPEND ); +} + +// ----------------------------------------------------------------------- + +sal_Bool Section::GetDictionary( Dictionary& rDict ) +{ + sal_Bool bRetValue = sal_False; + + Dictionary aDict; + PropEntry* pProp; + + for ( pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() ) + { + if ( pProp->mnId == 0 ) + break; + } + if ( pProp ) + { + sal_uInt32 nDictCount, nId, nSize, nPos; + SvMemoryStream aStream( (sal_Int8*)pProp->mpBuf, pProp->mnSize, STREAM_READ ); + aStream.Seek( STREAM_SEEK_TO_BEGIN ); + aStream >> nDictCount; + for ( sal_uInt32 i = 0; i < nDictCount; i++ ) + { + aStream >> nId >> nSize; + if ( nSize ) + { + String aString; + nPos = aStream.Tell(); + try + { + sal_Char* pString = new sal_Char[ nSize ]; + aStream.Read( pString, nSize ); + if ( mnTextEnc == RTL_TEXTENCODING_UCS2 ) + { + nSize >>= 1; + aStream.Seek( nPos ); + sal_Unicode* pWString = (sal_Unicode*)pString; + for ( i = 0; i < nSize; i++ ) + aStream >> pWString[ i ]; + aString = String( pWString, lcl_getMaxSafeStrLen(nSize) ); + } + else + aString = String( ByteString( pString, lcl_getMaxSafeStrLen(nSize) ), mnTextEnc ); + delete[] pString; + } + catch( const std::bad_alloc& ) + { + DBG_ERROR( "sd Section::GetDictionary bad alloc" ); + } + if ( !aString.Len() ) + break; + aDict.AddProperty( nId, aString ); + } + bRetValue = sal_True; + } + } + rDict = aDict; + return bRetValue; +} + +// ----------------------------------------------------------------------- + +Section::~Section() +{ + for ( PropEntry* pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() ) + delete pProp; +} + +// ----------------------------------------------------------------------- + +void Section::Read( SvStorageStream *pStrm ) +{ + sal_uInt32 i, nSecOfs, nSecSize, nPropCount, nPropId, nPropOfs, nPropType, nPropSize, nCurrent, nVectorCount, nTemp, nStrmSize; + nSecOfs = pStrm->Tell(); + + pStrm->Seek( STREAM_SEEK_TO_END ); + nStrmSize = pStrm->Tell(); + pStrm->Seek( nSecOfs ); + + mnTextEnc = RTL_TEXTENCODING_MS_1252; + *pStrm >> nSecSize >> nPropCount; + while( nPropCount-- && ( pStrm->GetError() == ERRCODE_NONE ) ) + { + *pStrm >> nPropId >> nPropOfs; + nCurrent = pStrm->Tell(); + pStrm->Seek( nPropOfs + nSecOfs ); + if ( nPropId ) // dictionary wird nicht eingelesen + { + + *pStrm >> nPropType; + + nPropSize = 4; + + if ( nPropType & VT_VECTOR ) + { + *pStrm >> nVectorCount; + nPropType &=~VT_VECTOR; + nPropSize += 4; + } + else + nVectorCount = 1; + + + sal_Bool bVariant = ( nPropType == VT_VARIANT ); + + for ( i = 0; nPropSize && ( i < nVectorCount ); i++ ) + { + if ( bVariant ) + { + *pStrm >> nPropType; + nPropSize += 4; + } + switch( nPropType ) + { + case VT_UI1 : + nPropSize++; + break; + + case VT_I2 : + case VT_UI2 : + case VT_BOOL : + nPropSize += 2; + break; + + case VT_I4 : + case VT_R4 : + case VT_UI4 : + case VT_ERROR : + nPropSize += 4; + break; + + case VT_I8 : + case VT_R8 : + case VT_CY : + case VT_UI8 : + case VT_DATE : + case VT_FILETIME : + nPropSize += 8; + break; + + case VT_BSTR : + *pStrm >> nTemp; + nPropSize += ( nTemp + 4 ); + break; + + case VT_LPSTR : + *pStrm >> nTemp; + nPropSize += ( nTemp + 4 ); + break; + + case VT_LPWSTR : + *pStrm >> nTemp; + nPropSize += ( nTemp << 1 ) + 4; + break; + + case VT_BLOB_OBJECT : + case VT_BLOB : + case VT_CF : + *pStrm >> nTemp; + nPropSize += ( nTemp + 4 ); + break; + + case VT_CLSID : + case VT_STREAM : + case VT_STORAGE : + case VT_STREAMED_OBJECT : + case VT_STORED_OBJECT : + case VT_VARIANT : + case VT_VECTOR : + default : + nPropSize = 0; + } + if ( nPropSize ) + { + if ( ( nVectorCount - i ) > 1 ) + pStrm->Seek( nPropOfs + nSecOfs + nPropSize ); + } + else + break; + } + if ( nPropSize ) + { + if ( nPropSize > nStrmSize ) + { + nPropCount = 0; + break; + } + pStrm->Seek( nPropOfs + nSecOfs ); + sal_uInt8* pBuf = new sal_uInt8[ nPropSize ]; + pStrm->Read( pBuf, nPropSize ); + AddProperty( nPropId, pBuf, nPropSize ); + delete[] pBuf; + } + if ( nPropId == 1 ) + { + PropItem aPropItem; + if ( GetProperty( 1, aPropItem ) ) + { + sal_uInt16 nCodePage; + aPropItem >> nPropType; + if ( nPropType == VT_I2 ) + { + aPropItem >> nCodePage; + + if ( nCodePage == 1200 ) + { + mnTextEnc = RTL_TEXTENCODING_UCS2; + } + else + { + mnTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage ); + if ( mnTextEnc == RTL_TEXTENCODING_DONTKNOW ) + mnTextEnc = RTL_TEXTENCODING_MS_1252; + } + } + else + { + mnTextEnc = RTL_TEXTENCODING_MS_1252; + } + } + } + } + else + { + sal_uInt32 nDictCount, nSize; + *pStrm >> nDictCount; + for ( i = 0; i < nDictCount; i++ ) + { + *pStrm >> nSize >> nSize; + pStrm->SeekRel( nSize ); + } + nSize = pStrm->Tell(); + pStrm->Seek( nPropOfs + nSecOfs ); + nSize -= pStrm->Tell(); + if ( nSize > nStrmSize ) + { + nPropCount = 0; + break; + } + sal_uInt8* pBuf = new sal_uInt8[ nSize ]; + pStrm->Read( pBuf, nSize ); + AddProperty( 0xffffffff, pBuf, nSize ); + delete[] pBuf; + } + pStrm->Seek( nCurrent ); + } + pStrm->Seek( nSecOfs + nSecSize ); +} + +// ----------------------------------------------------------------------- + +Section& Section::operator=( Section& rSection ) +{ + PropEntry* pProp; + + if ( this != &rSection ) + { + memcpy( (void*)aFMTID, (void*)rSection.aFMTID, 16 ); + for ( pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() ) + delete pProp; + Clear(); + for ( pProp = (PropEntry*)rSection.First(); pProp; pProp = (PropEntry*)rSection.Next() ) + Insert( new PropEntry( *pProp ), LIST_APPEND ); + } + return *this; +} + +// ----------------------------------------------------------------------- + +PropRead::PropRead( SvStorage& rStorage, const String& rName ) : + mbStatus ( sal_False ), + mnByteOrder ( 0xfffe ), + mnFormat ( 0 ), + mnVersionLo ( 4 ), + mnVersionHi ( 2 ) +{ + if ( rStorage.IsStream( rName ) ) + { + mpSvStream = rStorage.OpenSotStream( rName, STREAM_STD_READ ); + if ( mpSvStream ) + { + mpSvStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + memset( mApplicationCLSID, 0, 16 ); + mbStatus = sal_True; + } + } +} + +// ----------------------------------------------------------------------- + +void PropRead::AddSection( Section& rSection ) +{ + Insert( new Section( rSection ), LIST_APPEND ); +} + +// ----------------------------------------------------------------------- + +const Section* PropRead::GetSection( const sal_uInt8* pFMTID ) +{ + Section* pSection; + + for ( pSection = (Section*)First(); pSection; pSection = (Section*)Next() ) + { + if ( memcmp( pSection->GetFMTID(), pFMTID, 16 ) == 0 ) + break; + } + return pSection; +} + +// ----------------------------------------------------------------------- + +PropRead::~PropRead() +{ + for ( Section* pSection = (Section*)First(); pSection; pSection = (Section*)Next() ) + delete pSection; +} + +// ----------------------------------------------------------------------- + +void PropRead::Read() +{ + for ( Section* pSection = (Section*)First(); pSection; pSection = (Section*)Next() ) + delete pSection; + Clear(); + if ( mbStatus ) + { + sal_uInt32 nSections; + sal_uInt32 nSectionOfs; + sal_uInt32 nCurrent; + *mpSvStream >> mnByteOrder >> mnFormat >> mnVersionLo >> mnVersionHi; + if ( mnByteOrder == 0xfffe ) + { + sal_uInt8* pSectCLSID = new sal_uInt8[ 16 ]; + mpSvStream->Read( mApplicationCLSID, 16 ); + *mpSvStream >> nSections; + if ( nSections > 2 ) // sj: PowerPoint documents are containing max 2 sections + { + mbStatus = sal_False; + } + else for ( sal_uInt32 i = 0; i < nSections; i++ ) + { + mpSvStream->Read( pSectCLSID, 16 ); + *mpSvStream >> nSectionOfs; + nCurrent = mpSvStream->Tell(); + mpSvStream->Seek( nSectionOfs ); + Section aSection( pSectCLSID ); + aSection.Read( mpSvStream ); + AddSection( aSection ); + mpSvStream->Seek( nCurrent ); + } + delete[] pSectCLSID; + } + } +} + +// ----------------------------------------------------------------------- + +PropRead& PropRead::operator=( PropRead& rPropRead ) +{ + Section* pSection; + + if ( this != &rPropRead ) + { + mbStatus = rPropRead.mbStatus; + mpSvStream = rPropRead.mpSvStream; + + mnByteOrder = rPropRead.mnByteOrder; + mnFormat = rPropRead.mnFormat; + mnVersionLo = rPropRead.mnVersionLo; + mnVersionHi = rPropRead.mnVersionHi; + memcpy( mApplicationCLSID, rPropRead.mApplicationCLSID, 16 ); + + for ( pSection = (Section*)First(); pSection; pSection = (Section*)Next() ) + delete pSection; + Clear(); + for ( pSection = (Section*)rPropRead.First(); pSection; pSection = (Section*)rPropRead.Next() ) + Insert( new Section( *pSection ), LIST_APPEND ); + } + return *this; +} |