/************************************************************************* * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sd.hxx" #include #include #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(); } // ----------------------------------------------------------------------- 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 ( (sal_uInt16)nItemSize ) { sal_Char* pString = new sal_Char[ (sal_uInt16)nItemSize ]; if ( mnTextEnc == RTL_TEXTENCODING_UCS2 ) { nItemSize >>= 1; if ( (sal_uInt16)nItemSize > 1 ) { sal_Unicode* pWString = (sal_Unicode*)pString; for ( i = 0; i < (sal_uInt16)nItemSize; i++ ) *this >> pWString[ i ]; rString = String( pWString, (sal_uInt16)nItemSize - 1 ); } else rString = String(); bRetValue = sal_True; } else { SvMemoryStream::Read( pString, (sal_uInt16)nItemSize ); if ( pString[ (sal_uInt16)nItemSize - 1 ] == 0 ) { if ( (sal_uInt16)nItemSize > 1 ) rString = String( ByteString( pString ), mnTextEnc ); else rString = String(); bRetValue = sal_True; } } delete[] pString; } if ( bAlign ) SeekRel( ( 4 - ( nItemSize & 3 ) ) & 3 ); // dword align } break; case VT_LPWSTR : { if ( nItemSize ) { sal_Unicode* pString = new sal_Unicode[ (sal_uInt16)nItemSize ]; for ( i = 0; i < (sal_uInt16)nItemSize; i++ ) *this >> pString[ i ]; if ( pString[ i - 1 ] == 0 ) { if ( (sal_uInt16)nItemSize > 1 ) rString = String( pString, (sal_uInt16)nItemSize - 1 ); else rString = String(); bRetValue = sal_True; } delete[] pString; } 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 ( (sal_uInt16)nSize ) { String aString; nPos = aStream.Tell(); sal_Char* pString = new sal_Char[ (sal_uInt16)nSize ]; aStream.Read( pString, (sal_uInt16)nSize ); if ( mnTextEnc == RTL_TEXTENCODING_UCS2 ) { nSize >>= 1; aStream.Seek( nPos ); sal_Unicode* pWString = (sal_Unicode*)pString; for ( i = 0; i < (sal_uInt16)nSize; i++ ) aStream >> pWString[ i ]; aString = String( pWString, (sal_uInt16)nSize - 1 ); } else aString = String( ByteString( pString, (sal_uInt16)nSize - 1 ), mnTextEnc ); delete[] pString; 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 ) { 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; }