summaryrefslogtreecommitdiffstats
path: root/sot/source/sdstor/storage.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sot/source/sdstor/storage.cxx
parentInitial commit. (diff)
downloadlibreoffice-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.cxx851
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: */