Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sot / source / sdstor / storage.cxx
blobeff6a4fdf6501d6cc4814d64a1b01df0427a0a95
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <com/sun/star/embed/XStorage.hpp>
24 #include <com/sun/star/embed/ElementModes.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <osl/file.hxx>
28 #include <sot/stg.hxx>
29 #include <sot/storinfo.hxx>
30 #include <sot/storage.hxx>
31 #include <sot/formats.hxx>
32 #include <sot/exchange.hxx>
33 #include <unotools/ucbstreamhelper.hxx>
34 #include <comphelper/diagnose_ex.hxx>
35 #include <tools/debug.hxx>
36 #include <tools/urlobj.hxx>
37 #include <unotools/ucbhelper.hxx>
38 #include <comphelper/fileformat.h>
39 #include <com/sun/star/uno/Reference.h>
41 #include <memory>
43 using namespace ::com::sun::star;
45 static SvLockBytesRef MakeLockBytes_Impl( const OUString & rName, StreamMode nMode )
47 SvLockBytesRef xLB;
48 if( !rName.isEmpty() )
50 SvStream * pFileStm = new SvFileStream( rName, nMode );
51 xLB = new SvLockBytes( pFileStm, true );
53 else
55 SvStream * pCacheStm = new SvMemoryStream();
56 xLB = new SvLockBytes( pCacheStm, true );
58 return xLB;
61 SotTempStream::SotTempStream( const OUString & rName, StreamMode nMode )
62 : SvStream( MakeLockBytes_Impl( rName, nMode ).get() )
64 if( nMode & StreamMode::WRITE )
65 m_isWritable = true;
66 else
67 m_isWritable = false;
70 SotTempStream::~SotTempStream()
72 FlushBuffer();
75 void SotTempStream::CopyTo( SotTempStream * pDestStm )
77 FlushBuffer(); // write all data
79 sal_uInt64 nPos = Tell(); // save position
80 Seek( 0 );
81 pDestStm->SetSize( 0 ); // empty target stream
83 constexpr int BUFSIZE = 64 * 1024;
84 std::unique_ptr<sal_uInt8[]> pMem(new sal_uInt8[ BUFSIZE ]);
85 sal_Int32 nRead;
86 while (0 != (nRead = ReadBytes(pMem.get(), BUFSIZE)))
88 if (nRead != static_cast<sal_Int32>(pDestStm->WriteBytes(pMem.get(), nRead)))
90 SetError( SVSTREAM_GENERALERROR );
91 break;
94 pMem.reset();
96 // set position
97 pDestStm->Seek( nPos );
98 Seek( nPos );
101 SotStorageStream::SotStorageStream( BaseStorageStream * pStm )
102 : pOwnStm(pStm)
104 assert( pStm );
105 if( StreamMode::WRITE & pStm->GetMode() )
106 m_isWritable = true;
107 else
108 m_isWritable = false;
110 SetError( pStm->GetError() );
111 pStm->ResetError();
114 SotStorageStream::~SotStorageStream()
116 Flush();
117 delete pOwnStm;
120 void SotStorageStream::ResetError()
122 SvStream::ResetError();
123 pOwnStm->ResetError();
126 std::size_t SotStorageStream::GetData(void* pData, std::size_t const nSize)
128 std::size_t nRet = pOwnStm->Read( pData, nSize );
129 SetError( pOwnStm->GetError() );
130 return nRet;
133 std::size_t SotStorageStream::PutData(const void* pData, std::size_t const nSize)
135 std::size_t nRet = pOwnStm->Write( pData, nSize );
136 SetError( pOwnStm->GetError() );
137 return nRet;
140 sal_uInt64 SotStorageStream::SeekPos(sal_uInt64 nPos)
142 sal_uInt64 nRet = pOwnStm->Seek( nPos );
143 SetError( pOwnStm->GetError() );
144 return nRet;
147 void SotStorageStream::FlushData()
149 pOwnStm->Flush();
150 SetError( pOwnStm->GetError() );
153 void SotStorageStream::SetSize(sal_uInt64 const nNewSize)
155 sal_uInt64 const nPos = Tell();
156 pOwnStm->SetSize( nNewSize );
157 SetError( pOwnStm->GetError() );
159 if( nNewSize < nPos )
160 // jump to the end
161 Seek( nNewSize );
164 sal_uInt32 SotStorageStream::GetSize() const
166 sal_uInt64 nSize = const_cast<SotStorageStream*>(this)->TellEnd();
167 return nSize;
170 sal_uInt64 SotStorageStream::TellEnd()
172 // Need to flush the buffer so we materialise the stream and return the correct answer
173 // otherwise we return a 0 value from StgEntry::GetSize
174 FlushBuffer();
176 return pOwnStm->GetSize();
179 void SotStorageStream::Commit()
181 pOwnStm->Flush();
182 if( pOwnStm->GetError() == ERRCODE_NONE )
183 pOwnStm->Commit();
184 SetError( pOwnStm->GetError() );
187 bool SotStorageStream::SetProperty( const OUString& rName, const css::uno::Any& rValue )
189 UCBStorageStream* pStg = dynamic_cast<UCBStorageStream*>( pOwnStm );
190 if ( pStg )
192 return pStg->SetProperty( rName, rValue );
194 else
196 OSL_FAIL("Not implemented!");
197 return false;
202 * SotStorage::SotStorage()
204 * A I... object must be passed to SvObject, because otherwise itself will
205 * create and define an IUnknown, so that all other I... objects would be
206 * destroyed with delete (Owner() == true).
207 * But IStorage objects are only used and not implemented by ourselves,
208 * therefore we pretend the IStorage object was passed from the outside
209 * and it will be freed with Release().
210 * The CreateStorage methods are needed to create an IStorage object before the
211 * call of SvObject (Own, !Own automatic).
212 * If CreateStorage has created an object, then the RefCounter was already
213 * incremented.
214 * The transfer is done in pStorageCTor and the variable is NULL, if it didn't
215 * work.
217 #define INIT_SotStorage() \
218 : m_pOwnStg( nullptr ) \
219 , m_pStorStm( nullptr ) \
220 , m_nError( ERRCODE_NONE ) \
221 , m_bIsRoot( false ) \
222 , m_bDelStm( false ) \
223 , m_nVersion( SOFFICE_FILEFORMAT_CURRENT )
225 #define ERASEMASK ( StreamMode::TRUNC | StreamMode::WRITE | StreamMode::SHARE_DENYALL )
227 SotStorage::SotStorage( const OUString & rName, StreamMode nMode )
228 INIT_SotStorage()
230 m_aName = rName; // save name
231 CreateStorage( true, nMode );
232 if ( IsOLEStorage() )
233 m_nVersion = SOFFICE_FILEFORMAT_50;
236 void SotStorage::CreateStorage( bool bForceUCBStorage, StreamMode nMode )
238 DBG_ASSERT( !m_pStorStm && !m_pOwnStg, "Use only in ctor!" );
239 if( !m_aName.isEmpty() )
241 // named storage
242 if( ( nMode & ERASEMASK ) == ERASEMASK )
243 ::utl::UCBContentHelper::Kill( m_aName );
245 INetURLObject aObj( m_aName );
246 if ( aObj.GetProtocol() == INetProtocol::NotValid )
248 OUString aURL;
249 osl::FileBase::getFileURLFromSystemPath( m_aName, aURL );
250 aObj.SetURL( aURL );
251 m_aName = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
254 // check the stream
255 m_pStorStm = ::utl::UcbStreamHelper::CreateStream( m_aName, nMode ).release();
256 if ( m_pStorStm && m_pStorStm->GetError() )
258 delete m_pStorStm;
259 m_pStorStm = nullptr;
262 if ( m_pStorStm )
264 // try as UCBStorage, next try as OLEStorage
265 bool bIsUCBStorage = UCBStorage::IsStorageFile( m_pStorStm );
266 if ( !bIsUCBStorage && bForceUCBStorage )
267 // if UCBStorage has priority, it should not be used only if it is really an OLEStorage
268 bIsUCBStorage = !Storage::IsStorageFile( m_pStorStm );
270 if ( bIsUCBStorage )
272 // UCBStorage always works directly on the UCB content, so discard the stream first
273 delete m_pStorStm;
274 m_pStorStm = nullptr;
275 m_pOwnStg = new UCBStorage( m_aName, nMode, true, true/*bIsRoot*/ );
277 else
279 // OLEStorage can be opened with a stream
280 m_pOwnStg = new Storage( *m_pStorStm, true );
281 m_bDelStm = true;
284 else if ( bForceUCBStorage )
286 m_pOwnStg = new UCBStorage( m_aName, nMode, true, true/*bIsRoot*/ );
287 SetError( ERRCODE_IO_NOTSUPPORTED );
289 else
291 m_pOwnStg = new Storage( m_aName, nMode, true );
292 SetError( ERRCODE_IO_NOTSUPPORTED );
295 else
297 // temporary storage
298 if ( bForceUCBStorage )
299 m_pOwnStg = new UCBStorage( m_aName, nMode, true, true/*bIsRoot*/ );
300 else
301 m_pOwnStg = new Storage( m_aName, nMode, true );
302 m_aName = m_pOwnStg->GetName();
305 SetError( m_pOwnStg->GetError() );
307 SignAsRoot( m_pOwnStg->IsRoot() );
310 SotStorage::SotStorage( bool bUCBStorage, const OUString & rName, StreamMode nMode )
311 INIT_SotStorage()
313 m_aName = rName;
314 CreateStorage( bUCBStorage, nMode );
315 if ( IsOLEStorage() )
316 m_nVersion = SOFFICE_FILEFORMAT_50;
319 SotStorage::SotStorage( BaseStorage * pStor )
320 INIT_SotStorage()
322 if ( pStor )
324 m_aName = pStor->GetName(); // save name
325 SignAsRoot( pStor->IsRoot() );
326 SetError( pStor->GetError() );
329 m_pOwnStg = pStor;
330 const ErrCode nErr = m_pOwnStg ? m_pOwnStg->GetError() : SVSTREAM_CANNOT_MAKE;
331 SetError( nErr );
332 if ( IsOLEStorage() )
333 m_nVersion = SOFFICE_FILEFORMAT_50;
336 SotStorage::SotStorage( bool bUCBStorage, SvStream & rStm )
337 INIT_SotStorage()
339 SetError( rStm.GetError() );
341 // try as UCBStorage, next try as OLEStorage
342 if ( UCBStorage::IsStorageFile( &rStm ) || bUCBStorage )
343 m_pOwnStg = new UCBStorage( rStm, false );
344 else
345 m_pOwnStg = new Storage( rStm, false );
347 SetError( m_pOwnStg->GetError() );
349 if ( IsOLEStorage() )
350 m_nVersion = SOFFICE_FILEFORMAT_50;
352 SignAsRoot( m_pOwnStg->IsRoot() );
355 SotStorage::SotStorage( SvStream & rStm )
356 INIT_SotStorage()
358 SetError( rStm.GetError() );
360 // try as UCBStorage, next try as OLEStorage
361 if ( UCBStorage::IsStorageFile( &rStm ) )
362 m_pOwnStg = new UCBStorage( rStm, false );
363 else
364 m_pOwnStg = new Storage( rStm, false );
366 SetError( m_pOwnStg->GetError() );
368 if ( IsOLEStorage() )
369 m_nVersion = SOFFICE_FILEFORMAT_50;
371 SignAsRoot( m_pOwnStg->IsRoot() );
374 SotStorage::SotStorage( SvStream * pStm, bool bDelete )
375 INIT_SotStorage()
377 SetError( pStm->GetError() );
379 // try as UCBStorage, next try as OLEStorage
380 if ( UCBStorage::IsStorageFile( pStm ) )
381 m_pOwnStg = new UCBStorage( *pStm, false );
382 else
383 m_pOwnStg = new Storage( *pStm, false );
385 SetError( m_pOwnStg->GetError() );
387 m_pStorStm = pStm;
388 m_bDelStm = bDelete;
389 if ( IsOLEStorage() )
390 m_nVersion = SOFFICE_FILEFORMAT_50;
392 SignAsRoot( m_pOwnStg->IsRoot() );
395 SotStorage::~SotStorage()
397 delete m_pOwnStg;
398 if( m_bDelStm )
399 delete m_pStorStm;
402 std::unique_ptr<SvMemoryStream> SotStorage::CreateMemoryStream()
404 std::unique_ptr<SvMemoryStream> pStm(new SvMemoryStream( 0x8000, 0x8000 ));
405 tools::SvRef<SotStorage> aStg = new SotStorage( *pStm );
406 if( CopyTo( aStg.get() ) )
408 aStg->Commit();
410 else
412 aStg.clear(); // release storage beforehand
413 pStm.reset();
415 return pStm;
418 bool SotStorage::IsStorageFile( const OUString & rFileName )
420 OUString aName( rFileName );
421 INetURLObject aObj( aName );
422 if ( aObj.GetProtocol() == INetProtocol::NotValid )
424 OUString aURL;
425 osl::FileBase::getFileURLFromSystemPath( aName, aURL );
426 aObj.SetURL( aURL );
427 aName = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
430 std::unique_ptr<SvStream> pStm(::utl::UcbStreamHelper::CreateStream( aName, StreamMode::STD_READ ));
431 bool bRet = SotStorage::IsStorageFile( pStm.get() );
432 return bRet;
435 bool SotStorage::IsStorageFile( SvStream* pStream )
437 /** code for new storages must come first! **/
438 if ( pStream )
440 sal_uInt64 nPos = pStream->Tell();
441 bool bRet = UCBStorage::IsStorageFile( pStream );
442 if ( !bRet )
443 bRet = Storage::IsStorageFile( pStream );
444 pStream->Seek( nPos );
445 return bRet;
447 else
448 return false;
451 const OUString & SotStorage::GetName() const
453 if( m_aName.isEmpty() && m_pOwnStg )
454 const_cast<SotStorage *>(this)->m_aName = m_pOwnStg->GetName();
455 return m_aName;
458 void SotStorage::SetClass( const SvGlobalName & rName,
459 SotClipboardFormatId nOriginalClipFormat,
460 const OUString & rUserTypeName )
462 if( m_pOwnStg )
463 m_pOwnStg->SetClass( rName, nOriginalClipFormat, rUserTypeName );
464 else
465 SetError( SVSTREAM_GENERALERROR );
468 SvGlobalName SotStorage::GetClassName()
470 SvGlobalName aGN;
471 if( m_pOwnStg )
472 aGN = m_pOwnStg->GetClassName();
473 else
474 SetError( SVSTREAM_GENERALERROR );
475 return aGN;
478 SotClipboardFormatId SotStorage::GetFormat()
480 SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
481 if( m_pOwnStg )
482 nFormat = m_pOwnStg->GetFormat();
483 else
484 SetError( SVSTREAM_GENERALERROR );
485 return nFormat;
488 OUString SotStorage::GetUserName()
490 OUString aName;
491 if( m_pOwnStg )
492 aName = m_pOwnStg->GetUserName();
493 else
494 SetError( SVSTREAM_GENERALERROR );
495 return aName;
498 void SotStorage::FillInfoList( SvStorageInfoList * pFillList ) const
500 if( m_pOwnStg )
501 m_pOwnStg->FillInfoList( pFillList );
504 bool SotStorage::CopyTo( SotStorage * pDestStg )
506 if( m_pOwnStg && pDestStg->m_pOwnStg )
508 m_pOwnStg->CopyTo( pDestStg->m_pOwnStg );
509 SetError( m_pOwnStg->GetError() );
510 pDestStg->m_aKey = m_aKey;
511 pDestStg->m_nVersion = m_nVersion;
513 else
514 SetError( SVSTREAM_GENERALERROR );
516 return ERRCODE_NONE == GetError();
519 bool SotStorage::Commit()
521 if( m_pOwnStg )
523 if( !m_pOwnStg->Commit() )
524 SetError( m_pOwnStg->GetError() );
526 else
527 SetError( SVSTREAM_GENERALERROR );
529 return ERRCODE_NONE == GetError();
532 tools::SvRef<SotStorageStream> SotStorage::OpenSotStream( const OUString & rEleName,
533 StreamMode nMode )
535 tools::SvRef<SotStorageStream> pStm;
536 if( m_pOwnStg )
538 // enable full Ole patches,
539 // regardless what is coming, only exclusively allowed
540 nMode |= StreamMode::SHARE_DENYALL;
541 ErrCode nE = m_pOwnStg->GetError();
542 BaseStorageStream * p = m_pOwnStg->OpenStream( rEleName, nMode );
543 pStm = new SotStorageStream( p );
545 if( !nE )
546 m_pOwnStg->ResetError(); // don't set error
547 if( nMode & StreamMode::TRUNC )
548 pStm->SetSize( 0 );
550 else
551 SetError( SVSTREAM_GENERALERROR );
553 return pStm;
556 SotStorage * SotStorage::OpenSotStorage( const OUString & rEleName,
557 StreamMode nMode,
558 bool transacted )
560 if( m_pOwnStg )
562 nMode |= StreamMode::SHARE_DENYALL;
563 ErrCode nE = m_pOwnStg->GetError();
564 BaseStorage * p = m_pOwnStg->OpenStorage(rEleName, nMode, !transacted);
565 if( p )
567 SotStorage * pStor = new SotStorage( p );
568 if( !nE )
569 m_pOwnStg->ResetError(); // don't set error
571 return pStor;
575 SetError( SVSTREAM_GENERALERROR );
577 return nullptr;
580 bool SotStorage::IsStorage( const OUString & rEleName ) const
582 // a little bit faster
583 if( m_pOwnStg )
584 return m_pOwnStg->IsStorage( rEleName );
586 return false;
589 bool SotStorage::IsStream( const OUString & rEleName ) const
591 // a little bit faster
592 if( m_pOwnStg )
593 return m_pOwnStg->IsStream( rEleName );
595 return false;
598 bool SotStorage::IsContained( const OUString & rEleName ) const
600 // a little bit faster
601 if( m_pOwnStg )
602 return m_pOwnStg->IsContained( rEleName );
604 return false;
607 bool SotStorage::Remove( const OUString & rEleName )
609 if( m_pOwnStg )
611 m_pOwnStg->Remove( rEleName );
612 SetError( m_pOwnStg->GetError() );
614 else
615 SetError( SVSTREAM_GENERALERROR );
617 return ERRCODE_NONE == GetError();
620 bool SotStorage::CopyTo( const OUString & rEleName,
621 SotStorage * pNewSt, const OUString & rNewName )
623 if( m_pOwnStg )
625 m_pOwnStg->CopyTo( rEleName, pNewSt->m_pOwnStg, rNewName );
626 SetError( m_pOwnStg->GetError() );
627 SetError( pNewSt->GetError() );
629 else
630 SetError( SVSTREAM_GENERALERROR );
632 return ERRCODE_NONE == GetError();
635 bool SotStorage::Validate()
637 DBG_ASSERT( m_bIsRoot, "Validate only if root storage" );
638 if( m_pOwnStg )
639 return m_pOwnStg->ValidateFAT();
640 else
641 return true;
644 bool SotStorage::IsOLEStorage() const
646 UCBStorage* pStg = dynamic_cast<UCBStorage*>( m_pOwnStg );
647 return !pStg;
650 bool SotStorage::IsOLEStorage( const OUString & rFileName )
652 return Storage::IsStorageFile( rFileName );
655 bool SotStorage::IsOLEStorage( SvStream* pStream )
657 return Storage::IsStorageFile( pStream );
660 SotStorage* SotStorage::OpenOLEStorage( const css::uno::Reference < css::embed::XStorage >& xStorage,
661 const OUString& rEleName, StreamMode nMode )
663 sal_Int32 nEleMode = embed::ElementModes::SEEKABLEREAD;
664 if ( nMode & StreamMode::WRITE )
665 nEleMode |= embed::ElementModes::WRITE;
666 if ( nMode & StreamMode::TRUNC )
667 nEleMode |= embed::ElementModes::TRUNCATE;
668 if ( nMode & StreamMode::NOCREATE )
669 nEleMode |= embed::ElementModes::NOCREATE;
671 std::unique_ptr<SvStream> pStream;
674 uno::Reference < io::XStream > xStream = xStorage->openStreamElement( rEleName, nEleMode );
676 // TODO/LATER: should it be done this way?
677 if ( nMode & StreamMode::WRITE )
679 uno::Reference < beans::XPropertySet > xStreamProps( xStream, uno::UNO_QUERY_THROW );
680 xStreamProps->setPropertyValue( "MediaType",
681 uno::Any( OUString( "application/vnd.sun.star.oleobject" ) ) );
684 pStream = utl::UcbStreamHelper::CreateStream( xStream );
686 catch ( uno::Exception& )
688 //TODO/LATER: ErrorHandling
689 pStream.reset( new SvMemoryStream );
690 pStream->SetError( ERRCODE_IO_GENERAL );
693 return new SotStorage( pStream.release(), true );
696 SotClipboardFormatId SotStorage::GetFormatID( const css::uno::Reference < css::embed::XStorage >& xStorage )
698 uno::Reference< beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY );
699 if ( !xProps.is() )
700 return SotClipboardFormatId::NONE;
702 OUString aMediaType;
705 xProps->getPropertyValue("MediaType") >>= aMediaType;
707 catch (uno::Exception const&)
709 TOOLS_INFO_EXCEPTION("sot", "SotStorage::GetFormatID");
712 if ( !aMediaType.isEmpty() )
714 css::datatransfer::DataFlavor aDataFlavor;
715 aDataFlavor.MimeType = aMediaType;
716 return SotExchange::GetFormat( aDataFlavor );
719 return SotClipboardFormatId::NONE;
722 sal_Int32 SotStorage::GetVersion( const css::uno::Reference < css::embed::XStorage >& xStorage )
724 SotClipboardFormatId nSotFormatID = SotStorage::GetFormatID( xStorage );
725 switch( nSotFormatID )
727 case SotClipboardFormatId::STARWRITER_8:
728 case SotClipboardFormatId::STARWRITER_8_TEMPLATE:
729 case SotClipboardFormatId::STARWRITERWEB_8:
730 case SotClipboardFormatId::STARWRITERGLOB_8:
731 case SotClipboardFormatId::STARWRITERGLOB_8_TEMPLATE:
732 case SotClipboardFormatId::STARDRAW_8:
733 case SotClipboardFormatId::STARDRAW_8_TEMPLATE:
734 case SotClipboardFormatId::STARIMPRESS_8:
735 case SotClipboardFormatId::STARIMPRESS_8_TEMPLATE:
736 case SotClipboardFormatId::STARCALC_8:
737 case SotClipboardFormatId::STARCALC_8_TEMPLATE:
738 case SotClipboardFormatId::STARCHART_8:
739 case SotClipboardFormatId::STARCHART_8_TEMPLATE:
740 case SotClipboardFormatId::STARMATH_8:
741 case SotClipboardFormatId::STARMATH_8_TEMPLATE:
742 return SOFFICE_FILEFORMAT_8;
743 case SotClipboardFormatId::STARWRITER_60:
744 case SotClipboardFormatId::STARWRITERWEB_60:
745 case SotClipboardFormatId::STARWRITERGLOB_60:
746 case SotClipboardFormatId::STARDRAW_60:
747 case SotClipboardFormatId::STARIMPRESS_60:
748 case SotClipboardFormatId::STARCALC_60:
749 case SotClipboardFormatId::STARCHART_60:
750 case SotClipboardFormatId::STARMATH_60:
751 return SOFFICE_FILEFORMAT_60;
752 default: break;
755 return 0;
758 namespace
760 void traverse(const tools::SvRef<SotStorage>& rStorage, std::vector<unsigned char>& rBuf)
762 SvStorageInfoList infos;
764 rStorage->FillInfoList(&infos);
766 for (const auto& info: infos)
768 if (info.IsStream())
770 // try to open and read all content
771 tools::SvRef<SotStorageStream> xStream(rStorage->OpenSotStream(info.GetName(), StreamMode::STD_READ));
772 const size_t nSize = xStream->GetSize();
773 const size_t nRead = xStream->ReadBytes(rBuf.data(), nSize);
774 SAL_INFO("sot", "Read " << nRead << "bytes");
776 else if (info.IsStorage())
778 tools::SvRef<SotStorage> xStorage(rStorage->OpenSotStorage(info.GetName(), StreamMode::STD_READ));
780 // continue with children
781 traverse(xStorage, rBuf);
787 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportOLE2(SvStream &rStream)
791 size_t nSize = rStream.remainingSize();
792 tools::SvRef<SotStorage> xRootStorage(new SotStorage(&rStream, false));
793 std::vector<unsigned char> aTmpBuf(nSize);
794 traverse(xRootStorage, aTmpBuf);
796 catch (...)
798 return false;
800 return true;
803 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */