a9cf09844e
Change-Id: I782a071672b8c1fa2a843637fc5d7e993dbe0ef2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167599 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
759 lines
21 KiB
C++
759 lines
21 KiB
C++
/* -*- 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 <comphelper/diagnose_ex.hxx>
|
|
#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;
|
|
|
|
std::unique_ptr<SvStream> SotTempStream::Create( const OUString & rName, StreamMode nMode )
|
|
{
|
|
if( !rName.isEmpty() )
|
|
{
|
|
return std::make_unique<SvFileStream>( rName, nMode );
|
|
}
|
|
else
|
|
{
|
|
return std::make_unique<SvMemoryStream>();
|
|
}
|
|
}
|
|
|
|
SotStorageStream::SotStorageStream( BaseStorageStream * pStm )
|
|
: pOwnStm(pStm)
|
|
{
|
|
assert( pStm );
|
|
if( StreamMode::WRITE & pStm->GetMode() )
|
|
m_isWritable = true;
|
|
else
|
|
m_isWritable = false;
|
|
|
|
SetError( pStm->GetError() );
|
|
pStm->ResetError();
|
|
}
|
|
|
|
SotStorageStream::~SotStorageStream()
|
|
{
|
|
Flush();
|
|
delete pOwnStm;
|
|
}
|
|
|
|
void SotStorageStream::ResetError()
|
|
{
|
|
SvStream::ResetError();
|
|
pOwnStm->ResetError();
|
|
}
|
|
|
|
std::size_t SotStorageStream::GetData(void* pData, std::size_t const nSize)
|
|
{
|
|
std::size_t nRet = pOwnStm->Read( pData, nSize );
|
|
SetError( pOwnStm->GetError() );
|
|
return nRet;
|
|
}
|
|
|
|
std::size_t SotStorageStream::PutData(const void* pData, std::size_t const nSize)
|
|
{
|
|
std::size_t nRet = pOwnStm->Write( pData, nSize );
|
|
SetError( pOwnStm->GetError() );
|
|
return nRet;
|
|
}
|
|
|
|
sal_uInt64 SotStorageStream::SeekPos(sal_uInt64 nPos)
|
|
{
|
|
sal_uInt64 nRet = pOwnStm->Seek( nPos );
|
|
SetError( pOwnStm->GetError() );
|
|
return nRet;
|
|
}
|
|
|
|
void SotStorageStream::FlushData()
|
|
{
|
|
pOwnStm->Flush();
|
|
SetError( pOwnStm->GetError() );
|
|
}
|
|
|
|
void SotStorageStream::SetSize(sal_uInt64 const nNewSize)
|
|
{
|
|
sal_uInt64 const nPos = Tell();
|
|
pOwnStm->SetSize( nNewSize );
|
|
SetError( pOwnStm->GetError() );
|
|
|
|
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();
|
|
|
|
return pOwnStm->GetSize();
|
|
}
|
|
|
|
void SotStorageStream::Commit()
|
|
{
|
|
pOwnStm->Flush();
|
|
if( pOwnStm->GetError() == ERRCODE_NONE )
|
|
pOwnStm->Commit();
|
|
SetError( pOwnStm->GetError() );
|
|
}
|
|
|
|
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() )
|
|
{
|
|
delete m_pStorStm;
|
|
m_pStorStm = nullptr;
|
|
}
|
|
|
|
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
|
|
delete m_pStorStm;
|
|
m_pStorStm = nullptr;
|
|
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 ));
|
|
rtl::Reference<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();
|
|
}
|
|
|
|
rtl::Reference<SotStorageStream> SotStorage::OpenSotStream(const OUString& rEleName,
|
|
StreamMode nMode )
|
|
{
|
|
rtl::Reference<SotStorageStream> pStm;
|
|
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;
|
|
}
|
|
|
|
rtl::Reference<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 )
|
|
{
|
|
rtl::Reference<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 );
|
|
}
|
|
|
|
rtl::Reference<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( u"MediaType"_ustr,
|
|
uno::Any( u"application/vnd.sun.star.oleobject"_ustr ) );
|
|
}
|
|
|
|
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(u"MediaType"_ustr) >>= 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 rtl::Reference<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
|
|
rtl::Reference<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())
|
|
{
|
|
rtl::Reference<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();
|
|
rtl::Reference<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: */
|