diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sot/source/sdstor/storage.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | sot/source/sdstor/storage.cxx | 851 |
1 files changed, 851 insertions, 0 deletions
diff --git a/sot/source/sdstor/storage.cxx b/sot/source/sdstor/storage.cxx new file mode 100644 index 000000000..f15fb22dd --- /dev/null +++ b/sot/source/sdstor/storage.cxx @@ -0,0 +1,851 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <sal/log.hxx> + +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <osl/file.hxx> +#include <sot/stg.hxx> +#include <sot/storinfo.hxx> +#include <sot/storage.hxx> +#include <sot/formats.hxx> +#include <sot/exchange.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <tools/diagnose_ex.h> +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <unotools/ucbhelper.hxx> +#include <comphelper/fileformat.h> +#include <com/sun/star/uno/Reference.h> + +#include <memory> + +using namespace ::com::sun::star; + +static SvLockBytesRef MakeLockBytes_Impl( const OUString & rName, StreamMode nMode ) +{ + SvLockBytesRef xLB; + if( !rName.isEmpty() ) + { + SvStream * pFileStm = new SvFileStream( rName, nMode ); + xLB = new SvLockBytes( pFileStm, true ); + } + else + { + SvStream * pCacheStm = new SvMemoryStream(); + xLB = new SvLockBytes( pCacheStm, true ); + } + return xLB; +} + +SotStorageStream::SotStorageStream( const OUString & rName, StreamMode nMode ) + : SvStream( MakeLockBytes_Impl( rName, nMode ).get() ) + , pOwnStm( nullptr ) +{ + if( nMode & StreamMode::WRITE ) + m_isWritable = true; + else + m_isWritable = false; +} + +SotStorageStream::SotStorageStream( BaseStorageStream * pStm ) +{ + if( pStm ) + { + if( StreamMode::WRITE & pStm->GetMode() ) + m_isWritable = true; + else + m_isWritable = false; + + pOwnStm = pStm; + SetError( pStm->GetError() ); + pStm->ResetError(); + } + else + { + pOwnStm = nullptr; + m_isWritable = true; + SetError( SVSTREAM_INVALID_PARAMETER ); + } +} + +SotStorageStream::~SotStorageStream() +{ + Flush(); //SetBufferSize(0); + delete pOwnStm; +} + +void SotStorageStream::ResetError() +{ + SvStream::ResetError(); + if( pOwnStm ) + pOwnStm->ResetError(); +} + +std::size_t SotStorageStream::GetData(void* pData, std::size_t const nSize) +{ + std::size_t nRet = 0; + + if( pOwnStm ) + { + nRet = pOwnStm->Read( pData, nSize ); + SetError( pOwnStm->GetError() ); + } + else + nRet = SvStream::GetData( pData, nSize ); + + return nRet; +} + +std::size_t SotStorageStream::PutData(const void* pData, std::size_t const nSize) +{ + std::size_t nRet = 0; + + if( pOwnStm ) + { + nRet = pOwnStm->Write( pData, nSize ); + SetError( pOwnStm->GetError() ); + } + else + nRet = SvStream::PutData( pData, nSize ); + return nRet; +} + +sal_uInt64 SotStorageStream::SeekPos(sal_uInt64 nPos) +{ + sal_uLong nRet = 0; + + if( pOwnStm ) + { + nRet = pOwnStm->Seek( nPos ); + SetError( pOwnStm->GetError() ); + } + else + nRet = SvStream::SeekPos( nPos ); + + return nRet; +} + +void SotStorageStream::FlushData() +{ + if( pOwnStm ) + { + pOwnStm->Flush(); + SetError( pOwnStm->GetError() ); + } + else + SvStream::FlushData(); +} + +void SotStorageStream::SetSize(sal_uInt64 const nNewSize) +{ + sal_uInt64 const nPos = Tell(); + if( pOwnStm ) + { + pOwnStm->SetSize( nNewSize ); + SetError( pOwnStm->GetError() ); + } + else + SvStream::SetSize( nNewSize ); + + if( nNewSize < nPos ) + // jump to the end + Seek( nNewSize ); +} + +sal_uInt32 SotStorageStream::GetSize() const +{ + sal_uInt64 nSize = const_cast<SotStorageStream*>(this)->TellEnd(); + return nSize; +} + +sal_uInt64 SotStorageStream::TellEnd() +{ + // Need to flush the buffer so we materialise the stream and return the correct answer + // otherwise we return a 0 value from StgEntry::GetSize + FlushBuffer(); + + if (pOwnStm) + return pOwnStm->GetSize(); + + return SvStream::TellEnd(); +} + +void SotStorageStream::CopyTo( SotStorageStream * pDestStm ) +{ + Flush(); // write all data + pDestStm->ClearBuffer(); + if( !pOwnStm || !pDestStm->pOwnStm ) + { + // If Ole2 or not only own StorageStreams + sal_uInt64 nPos = Tell(); // save position + Seek( 0 ); + pDestStm->SetSize( 0 ); // empty target stream + + std::unique_ptr<sal_uInt8[]> pMem(new sal_uInt8[ 8192 ]); + sal_uLong nRead; + while (0 != (nRead = ReadBytes(pMem.get(), 8192))) + { + if (nRead != pDestStm->WriteBytes(pMem.get(), nRead)) + { + SetError( SVSTREAM_GENERALERROR ); + break; + } + } + pMem.reset(); + // set position + pDestStm->Seek( nPos ); + Seek( nPos ); + } + else + { + pOwnStm->CopyTo( pDestStm->pOwnStm ); + SetError( pOwnStm->GetError() ); + } +} + +bool SotStorageStream::Commit() +{ + if( pOwnStm ) + { + pOwnStm->Flush(); + if( pOwnStm->GetError() == ERRCODE_NONE ) + pOwnStm->Commit(); + SetError( pOwnStm->GetError() ); + } + return GetError() == ERRCODE_NONE; +} + +bool SotStorageStream::SetProperty( const OUString& rName, const css::uno::Any& rValue ) +{ + UCBStorageStream* pStg = dynamic_cast<UCBStorageStream*>( pOwnStm ); + if ( pStg ) + { + return pStg->SetProperty( rName, rValue ); + } + else + { + OSL_FAIL("Not implemented!"); + return false; + } +} + +/** + * SotStorage::SotStorage() + * + * A I... object must be passed to SvObject, because otherwise itself will + * create and define an IUnknown, so that all other I... objects would be + * destroyed with delete (Owner() == true). + * But IStorage objects are only used and not implemented by ourselves, + * therefore we pretend the IStorage object was passed from the outside + * and it will be freed with Release(). + * The CreateStorage methods are needed to create an IStorage object before the + * call of SvObject (Own, !Own automatic). + * If CreateStorage has created an object, then the RefCounter was already + * incremented. + * The transfer is done in pStorageCTor and the variable is NULL, if it didn't + * work. + */ +#define INIT_SotStorage() \ + : m_pOwnStg( nullptr ) \ + , m_pStorStm( nullptr ) \ + , m_nError( ERRCODE_NONE ) \ + , m_bIsRoot( false ) \ + , m_bDelStm( false ) \ + , m_nVersion( SOFFICE_FILEFORMAT_CURRENT ) + +#define ERASEMASK ( StreamMode::TRUNC | StreamMode::WRITE | StreamMode::SHARE_DENYALL ) + +SotStorage::SotStorage( const OUString & rName, StreamMode nMode ) + INIT_SotStorage() +{ + m_aName = rName; // save name + CreateStorage( true, nMode ); + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; +} + +void SotStorage::CreateStorage( bool bForceUCBStorage, StreamMode nMode ) +{ + DBG_ASSERT( !m_pStorStm && !m_pOwnStg, "Use only in ctor!" ); + if( !m_aName.isEmpty() ) + { + // named storage + if( ( nMode & ERASEMASK ) == ERASEMASK ) + ::utl::UCBContentHelper::Kill( m_aName ); + + INetURLObject aObj( m_aName ); + if ( aObj.GetProtocol() == INetProtocol::NotValid ) + { + OUString aURL; + osl::FileBase::getFileURLFromSystemPath( m_aName, aURL ); + aObj.SetURL( aURL ); + m_aName = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + } + + // check the stream + m_pStorStm = ::utl::UcbStreamHelper::CreateStream( m_aName, nMode ).release(); + if ( m_pStorStm && m_pStorStm->GetError() ) + DELETEZ( m_pStorStm ); + + if ( m_pStorStm ) + { + // try as UCBStorage, next try as OLEStorage + bool bIsUCBStorage = UCBStorage::IsStorageFile( m_pStorStm ); + if ( !bIsUCBStorage && bForceUCBStorage ) + // if UCBStorage has priority, it should not be used only if it is really an OLEStorage + bIsUCBStorage = !Storage::IsStorageFile( m_pStorStm ); + + if ( bIsUCBStorage ) + { + // UCBStorage always works directly on the UCB content, so discard the stream first + DELETEZ( m_pStorStm ); + m_pOwnStg = new UCBStorage( m_aName, nMode, true, true/*bIsRoot*/ ); + } + else + { + // OLEStorage can be opened with a stream + m_pOwnStg = new Storage( *m_pStorStm, true ); + m_bDelStm = true; + } + } + else if ( bForceUCBStorage ) + { + m_pOwnStg = new UCBStorage( m_aName, nMode, true, true/*bIsRoot*/ ); + SetError( ERRCODE_IO_NOTSUPPORTED ); + } + else + { + m_pOwnStg = new Storage( m_aName, nMode, true ); + SetError( ERRCODE_IO_NOTSUPPORTED ); + } + } + else + { + // temporary storage + if ( bForceUCBStorage ) + m_pOwnStg = new UCBStorage( m_aName, nMode, true, true/*bIsRoot*/ ); + else + m_pOwnStg = new Storage( m_aName, nMode, true ); + m_aName = m_pOwnStg->GetName(); + } + + SetError( m_pOwnStg->GetError() ); + + SignAsRoot( m_pOwnStg->IsRoot() ); +} + +SotStorage::SotStorage( bool bUCBStorage, const OUString & rName, StreamMode nMode ) + INIT_SotStorage() +{ + m_aName = rName; + CreateStorage( bUCBStorage, nMode ); + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; +} + +SotStorage::SotStorage( BaseStorage * pStor ) + INIT_SotStorage() +{ + if ( pStor ) + { + m_aName = pStor->GetName(); // save name + SignAsRoot( pStor->IsRoot() ); + SetError( pStor->GetError() ); + } + + m_pOwnStg = pStor; + const ErrCode nErr = m_pOwnStg ? m_pOwnStg->GetError() : SVSTREAM_CANNOT_MAKE; + SetError( nErr ); + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; +} + +SotStorage::SotStorage( bool bUCBStorage, SvStream & rStm ) + INIT_SotStorage() +{ + SetError( rStm.GetError() ); + + // try as UCBStorage, next try as OLEStorage + if ( UCBStorage::IsStorageFile( &rStm ) || bUCBStorage ) + m_pOwnStg = new UCBStorage( rStm, false ); + else + m_pOwnStg = new Storage( rStm, false ); + + SetError( m_pOwnStg->GetError() ); + + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; + + SignAsRoot( m_pOwnStg->IsRoot() ); +} + +SotStorage::SotStorage( SvStream & rStm ) + INIT_SotStorage() +{ + SetError( rStm.GetError() ); + + // try as UCBStorage, next try as OLEStorage + if ( UCBStorage::IsStorageFile( &rStm ) ) + m_pOwnStg = new UCBStorage( rStm, false ); + else + m_pOwnStg = new Storage( rStm, false ); + + SetError( m_pOwnStg->GetError() ); + + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; + + SignAsRoot( m_pOwnStg->IsRoot() ); +} + +SotStorage::SotStorage( SvStream * pStm, bool bDelete ) + INIT_SotStorage() +{ + SetError( pStm->GetError() ); + + // try as UCBStorage, next try as OLEStorage + if ( UCBStorage::IsStorageFile( pStm ) ) + m_pOwnStg = new UCBStorage( *pStm, false ); + else + m_pOwnStg = new Storage( *pStm, false ); + + SetError( m_pOwnStg->GetError() ); + + m_pStorStm = pStm; + m_bDelStm = bDelete; + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; + + SignAsRoot( m_pOwnStg->IsRoot() ); +} + +SotStorage::~SotStorage() +{ + delete m_pOwnStg; + if( m_bDelStm ) + delete m_pStorStm; +} + +std::unique_ptr<SvMemoryStream> SotStorage::CreateMemoryStream() +{ + std::unique_ptr<SvMemoryStream> pStm(new SvMemoryStream( 0x8000, 0x8000 )); + tools::SvRef<SotStorage> aStg = new SotStorage( *pStm ); + if( CopyTo( aStg.get() ) ) + { + aStg->Commit(); + } + else + { + aStg.clear(); // release storage beforehand + pStm.reset(); + } + return pStm; +} + +bool SotStorage::IsStorageFile( const OUString & rFileName ) +{ + OUString aName( rFileName ); + INetURLObject aObj( aName ); + if ( aObj.GetProtocol() == INetProtocol::NotValid ) + { + OUString aURL; + osl::FileBase::getFileURLFromSystemPath( aName, aURL ); + aObj.SetURL( aURL ); + aName = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + } + + std::unique_ptr<SvStream> pStm(::utl::UcbStreamHelper::CreateStream( aName, StreamMode::STD_READ )); + bool bRet = SotStorage::IsStorageFile( pStm.get() ); + return bRet; +} + +bool SotStorage::IsStorageFile( SvStream* pStream ) +{ + /** code for new storages must come first! **/ + if ( pStream ) + { + sal_uInt64 nPos = pStream->Tell(); + bool bRet = UCBStorage::IsStorageFile( pStream ); + if ( !bRet ) + bRet = Storage::IsStorageFile( pStream ); + pStream->Seek( nPos ); + return bRet; + } + else + return false; +} + +const OUString & SotStorage::GetName() const +{ + if( m_aName.isEmpty() && m_pOwnStg ) + const_cast<SotStorage *>(this)->m_aName = m_pOwnStg->GetName(); + return m_aName; +} + +void SotStorage::SetClass( const SvGlobalName & rName, + SotClipboardFormatId nOriginalClipFormat, + const OUString & rUserTypeName ) +{ + if( m_pOwnStg ) + m_pOwnStg->SetClass( rName, nOriginalClipFormat, rUserTypeName ); + else + SetError( SVSTREAM_GENERALERROR ); +} + +SvGlobalName SotStorage::GetClassName() +{ + SvGlobalName aGN; + if( m_pOwnStg ) + aGN = m_pOwnStg->GetClassName(); + else + SetError( SVSTREAM_GENERALERROR ); + return aGN; +} + +SotClipboardFormatId SotStorage::GetFormat() +{ + SotClipboardFormatId nFormat = SotClipboardFormatId::NONE; + if( m_pOwnStg ) + nFormat = m_pOwnStg->GetFormat(); + else + SetError( SVSTREAM_GENERALERROR ); + return nFormat; +} + +OUString SotStorage::GetUserName() +{ + OUString aName; + if( m_pOwnStg ) + aName = m_pOwnStg->GetUserName(); + else + SetError( SVSTREAM_GENERALERROR ); + return aName; +} + +void SotStorage::FillInfoList( SvStorageInfoList * pFillList ) const +{ + if( m_pOwnStg ) + m_pOwnStg->FillInfoList( pFillList ); +} + +bool SotStorage::CopyTo( SotStorage * pDestStg ) +{ + if( m_pOwnStg && pDestStg->m_pOwnStg ) + { + m_pOwnStg->CopyTo( pDestStg->m_pOwnStg ); + SetError( m_pOwnStg->GetError() ); + pDestStg->m_aKey = m_aKey; + pDestStg->m_nVersion = m_nVersion; + } + else + SetError( SVSTREAM_GENERALERROR ); + + return ERRCODE_NONE == GetError(); +} + +bool SotStorage::Commit() +{ + if( m_pOwnStg ) + { + if( !m_pOwnStg->Commit() ) + SetError( m_pOwnStg->GetError() ); + } + else + SetError( SVSTREAM_GENERALERROR ); + + return ERRCODE_NONE == GetError(); +} + +SotStorageStream * SotStorage::OpenSotStream( const OUString & rEleName, + StreamMode nMode ) +{ + SotStorageStream * pStm = nullptr; + if( m_pOwnStg ) + { + // enable full Ole patches, + // regardless what is coming, only exclusively allowed + nMode |= StreamMode::SHARE_DENYALL; + ErrCode nE = m_pOwnStg->GetError(); + BaseStorageStream * p = m_pOwnStg->OpenStream( rEleName, nMode ); + pStm = new SotStorageStream( p ); + + if( !nE ) + m_pOwnStg->ResetError(); // don't set error + if( nMode & StreamMode::TRUNC ) + pStm->SetSize( 0 ); + } + else + SetError( SVSTREAM_GENERALERROR ); + + return pStm; +} + +SotStorage * SotStorage::OpenSotStorage( const OUString & rEleName, + StreamMode nMode, + bool transacted ) +{ + if( m_pOwnStg ) + { + nMode |= StreamMode::SHARE_DENYALL; + ErrCode nE = m_pOwnStg->GetError(); + BaseStorage * p = m_pOwnStg->OpenStorage(rEleName, nMode, !transacted); + if( p ) + { + SotStorage * pStor = new SotStorage( p ); + if( !nE ) + m_pOwnStg->ResetError(); // don't set error + + return pStor; + } + } + + SetError( SVSTREAM_GENERALERROR ); + + return nullptr; +} + +bool SotStorage::IsStorage( const OUString & rEleName ) const +{ + // a little bit faster + if( m_pOwnStg ) + return m_pOwnStg->IsStorage( rEleName ); + + return false; +} + +bool SotStorage::IsStream( const OUString & rEleName ) const +{ + // a little bit faster + if( m_pOwnStg ) + return m_pOwnStg->IsStream( rEleName ); + + return false; +} + +bool SotStorage::IsContained( const OUString & rEleName ) const +{ + // a little bit faster + if( m_pOwnStg ) + return m_pOwnStg->IsContained( rEleName ); + + return false; +} + +bool SotStorage::Remove( const OUString & rEleName ) +{ + if( m_pOwnStg ) + { + m_pOwnStg->Remove( rEleName ); + SetError( m_pOwnStg->GetError() ); + } + else + SetError( SVSTREAM_GENERALERROR ); + + return ERRCODE_NONE == GetError(); +} + +bool SotStorage::CopyTo( const OUString & rEleName, + SotStorage * pNewSt, const OUString & rNewName ) +{ + if( m_pOwnStg ) + { + m_pOwnStg->CopyTo( rEleName, pNewSt->m_pOwnStg, rNewName ); + SetError( m_pOwnStg->GetError() ); + SetError( pNewSt->GetError() ); + } + else + SetError( SVSTREAM_GENERALERROR ); + + return ERRCODE_NONE == GetError(); +} + +bool SotStorage::Validate() +{ + DBG_ASSERT( m_bIsRoot, "Validate only if root storage" ); + if( m_pOwnStg ) + return m_pOwnStg->ValidateFAT(); + else + return true; +} + +bool SotStorage::IsOLEStorage() const +{ + UCBStorage* pStg = dynamic_cast<UCBStorage*>( m_pOwnStg ); + return !pStg; +} + +bool SotStorage::IsOLEStorage( const OUString & rFileName ) +{ + return Storage::IsStorageFile( rFileName ); +} + +bool SotStorage::IsOLEStorage( SvStream* pStream ) +{ + return Storage::IsStorageFile( pStream ); +} + +SotStorage* SotStorage::OpenOLEStorage( const css::uno::Reference < css::embed::XStorage >& xStorage, + const OUString& rEleName, StreamMode nMode ) +{ + sal_Int32 nEleMode = embed::ElementModes::SEEKABLEREAD; + if ( nMode & StreamMode::WRITE ) + nEleMode |= embed::ElementModes::WRITE; + if ( nMode & StreamMode::TRUNC ) + nEleMode |= embed::ElementModes::TRUNCATE; + if ( nMode & StreamMode::NOCREATE ) + nEleMode |= embed::ElementModes::NOCREATE; + + std::unique_ptr<SvStream> pStream; + try + { + uno::Reference < io::XStream > xStream = xStorage->openStreamElement( rEleName, nEleMode ); + + // TODO/LATER: should it be done this way? + if ( nMode & StreamMode::WRITE ) + { + uno::Reference < beans::XPropertySet > xStreamProps( xStream, uno::UNO_QUERY_THROW ); + xStreamProps->setPropertyValue( "MediaType", + uno::makeAny( OUString( "application/vnd.sun.star.oleobject" ) ) ); + } + + pStream = utl::UcbStreamHelper::CreateStream( xStream ); + } + catch ( uno::Exception& ) + { + //TODO/LATER: ErrorHandling + pStream.reset( new SvMemoryStream ); + pStream->SetError( ERRCODE_IO_GENERAL ); + } + + return new SotStorage( pStream.release(), true ); +} + +SotClipboardFormatId SotStorage::GetFormatID( const css::uno::Reference < css::embed::XStorage >& xStorage ) +{ + uno::Reference< beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY ); + if ( !xProps.is() ) + return SotClipboardFormatId::NONE; + + OUString aMediaType; + try + { + xProps->getPropertyValue("MediaType") >>= aMediaType; + } + catch (uno::Exception const&) + { + TOOLS_INFO_EXCEPTION("sot", "SotStorage::GetFormatID"); + } + + if ( !aMediaType.isEmpty() ) + { + css::datatransfer::DataFlavor aDataFlavor; + aDataFlavor.MimeType = aMediaType; + return SotExchange::GetFormat( aDataFlavor ); + } + + return SotClipboardFormatId::NONE; +} + +sal_Int32 SotStorage::GetVersion( const css::uno::Reference < css::embed::XStorage >& xStorage ) +{ + SotClipboardFormatId nSotFormatID = SotStorage::GetFormatID( xStorage ); + switch( nSotFormatID ) + { + case SotClipboardFormatId::STARWRITER_8: + case SotClipboardFormatId::STARWRITER_8_TEMPLATE: + case SotClipboardFormatId::STARWRITERWEB_8: + case SotClipboardFormatId::STARWRITERGLOB_8: + case SotClipboardFormatId::STARWRITERGLOB_8_TEMPLATE: + case SotClipboardFormatId::STARDRAW_8: + case SotClipboardFormatId::STARDRAW_8_TEMPLATE: + case SotClipboardFormatId::STARIMPRESS_8: + case SotClipboardFormatId::STARIMPRESS_8_TEMPLATE: + case SotClipboardFormatId::STARCALC_8: + case SotClipboardFormatId::STARCALC_8_TEMPLATE: + case SotClipboardFormatId::STARCHART_8: + case SotClipboardFormatId::STARCHART_8_TEMPLATE: + case SotClipboardFormatId::STARMATH_8: + case SotClipboardFormatId::STARMATH_8_TEMPLATE: + return SOFFICE_FILEFORMAT_8; + case SotClipboardFormatId::STARWRITER_60: + case SotClipboardFormatId::STARWRITERWEB_60: + case SotClipboardFormatId::STARWRITERGLOB_60: + case SotClipboardFormatId::STARDRAW_60: + case SotClipboardFormatId::STARIMPRESS_60: + case SotClipboardFormatId::STARCALC_60: + case SotClipboardFormatId::STARCHART_60: + case SotClipboardFormatId::STARMATH_60: + return SOFFICE_FILEFORMAT_60; + default: break; + } + + return 0; +} + +namespace +{ + void traverse(const tools::SvRef<SotStorage>& rStorage, std::vector<unsigned char>& rBuf) + { + SvStorageInfoList infos; + + rStorage->FillInfoList(&infos); + + for (const auto& info: infos) + { + if (info.IsStream()) + { + // try to open and read all content + tools::SvRef<SotStorageStream> xStream(rStorage->OpenSotStream(info.GetName(), StreamMode::STD_READ)); + const size_t nSize = xStream->GetSize(); + const size_t nRead = xStream->ReadBytes(rBuf.data(), nSize); + SAL_INFO("sot", "Read " << nRead << "bytes"); + } + else if (info.IsStorage()) + { + tools::SvRef<SotStorage> xStorage(rStorage->OpenSotStorage(info.GetName(), StreamMode::STD_READ)); + + // continue with children + traverse(xStorage, rBuf); + } + } + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportOLE2(SvStream &rStream) +{ + try + { + size_t nSize = rStream.remainingSize(); + tools::SvRef<SotStorage> xRootStorage(new SotStorage(&rStream, false)); + std::vector<unsigned char> aTmpBuf(nSize); + traverse(xRootStorage, aTmpBuf); + } + catch (...) + { + return false; + } + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |