lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / sot / source / sdstor / storage.cxx
blobbc78bddbbe043965bfbe02a2bd40c58c17d885e2
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 <rtl/digest.h>
28 #include <osl/file.hxx>
29 #include <sot/stg.hxx>
30 #include <sot/storinfo.hxx>
31 #include <sot/storage.hxx>
32 #include <sot/formats.hxx>
33 #include <sot/exchange.hxx>
34 #include <unotools/ucbstreamhelper.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>
40 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
41 #include <ucbhelper/content.hxx>
43 #include <memory>
45 using namespace ::com::sun::star;
47 static SvLockBytesRef MakeLockBytes_Impl( const OUString & rName, StreamMode nMode )
49 SvLockBytesRef xLB;
50 if( !rName.isEmpty() )
52 SvStream * pFileStm = new SvFileStream( rName, nMode );
53 xLB = new SvLockBytes( pFileStm, true );
55 else
57 SvStream * pCacheStm = new SvMemoryStream();
58 xLB = new SvLockBytes( pCacheStm, true );
60 return xLB;
63 SotStorageStream::SotStorageStream( const OUString & rName, StreamMode nMode )
64 : SvStream( MakeLockBytes_Impl( rName, nMode ).get() )
65 , pOwnStm( nullptr )
67 if( nMode & StreamMode::WRITE )
68 m_isWritable = true;
69 else
70 m_isWritable = false;
73 SotStorageStream::SotStorageStream( BaseStorageStream * pStm )
75 if( pStm )
77 if( StreamMode::WRITE & pStm->GetMode() )
78 m_isWritable = true;
79 else
80 m_isWritable = false;
82 pOwnStm = pStm;
83 SetError( pStm->GetError() );
84 pStm->ResetError();
86 else
88 pOwnStm = nullptr;
89 m_isWritable = true;
90 SetError( SVSTREAM_INVALID_PARAMETER );
94 SotStorageStream::~SotStorageStream()
96 Flush(); //SetBufferSize(0);
97 delete pOwnStm;
100 void SotStorageStream::ResetError()
102 SvStream::ResetError();
103 if( pOwnStm )
104 pOwnStm->ResetError();
107 std::size_t SotStorageStream::GetData(void* pData, std::size_t const nSize)
109 std::size_t nRet = 0;
111 if( pOwnStm )
113 nRet = pOwnStm->Read( pData, nSize );
114 SetError( pOwnStm->GetError() );
116 else
117 nRet = SvStream::GetData( pData, nSize );
119 return nRet;
122 std::size_t SotStorageStream::PutData(const void* pData, std::size_t const nSize)
124 std::size_t nRet = 0;
126 if( pOwnStm )
128 nRet = pOwnStm->Write( pData, nSize );
129 SetError( pOwnStm->GetError() );
131 else
132 nRet = SvStream::PutData( pData, nSize );
133 return nRet;
136 sal_uInt64 SotStorageStream::SeekPos(sal_uInt64 nPos)
138 sal_uLong nRet = 0;
140 if( pOwnStm )
142 nRet = pOwnStm->Seek( nPos );
143 SetError( pOwnStm->GetError() );
145 else
146 nRet = SvStream::SeekPos( nPos );
148 return nRet;
151 void SotStorageStream::FlushData()
153 if( pOwnStm )
155 pOwnStm->Flush();
156 SetError( pOwnStm->GetError() );
158 else
159 SvStream::FlushData();
162 void SotStorageStream::SetSize(sal_uInt64 const nNewSize)
164 sal_uInt64 const nPos = Tell();
165 if( pOwnStm )
167 pOwnStm->SetSize( nNewSize );
168 SetError( pOwnStm->GetError() );
170 else
171 SvStream::SetSize( nNewSize );
173 if( nNewSize < nPos )
174 // jump to the end
175 Seek( nNewSize );
178 sal_uInt32 SotStorageStream::GetSize() const
180 sal_uInt64 nSize = const_cast<SotStorageStream*>(this)->TellEnd();
181 return nSize;
184 sal_uInt64 SotStorageStream::TellEnd()
186 // Need to flush the buffer so we materialise the stream and return the correct answer
187 // otherwise we return a 0 value from StgEntry::GetSize
188 FlushBuffer(true);
190 if (pOwnStm)
191 return pOwnStm->GetSize();
193 return SvStream::TellEnd();
196 void SotStorageStream::CopyTo( SotStorageStream * pDestStm )
198 Flush(); // write all data
199 pDestStm->ClearBuffer();
200 if( !pOwnStm || !pDestStm->pOwnStm )
202 // If Ole2 or not only own StorageStreams
203 sal_uInt64 nPos = Tell(); // save position
204 Seek( 0 );
205 pDestStm->SetSize( 0 ); // empty target stream
207 std::unique_ptr<sal_uInt8[]> pMem(new sal_uInt8[ 8192 ]);
208 sal_uLong nRead;
209 while (0 != (nRead = ReadBytes(pMem.get(), 8192)))
211 if (nRead != pDestStm->WriteBytes(pMem.get(), nRead))
213 SetError( SVSTREAM_GENERALERROR );
214 break;
217 pMem.reset();
218 // set position
219 pDestStm->Seek( nPos );
220 Seek( nPos );
222 else
224 pOwnStm->CopyTo( pDestStm->pOwnStm );
225 SetError( pOwnStm->GetError() );
229 bool SotStorageStream::Commit()
231 if( pOwnStm )
233 pOwnStm->Flush();
234 if( pOwnStm->GetError() == ERRCODE_NONE )
235 pOwnStm->Commit();
236 SetError( pOwnStm->GetError() );
238 return GetError() == ERRCODE_NONE;
241 bool SotStorageStream::SetProperty( const OUString& rName, const css::uno::Any& rValue )
243 UCBStorageStream* pStg = dynamic_cast<UCBStorageStream*>( pOwnStm );
244 if ( pStg )
246 return pStg->SetProperty( rName, rValue );
248 else
250 OSL_FAIL("Not implemented!");
251 return false;
256 * SotStorage::SotStorage()
258 * A I.. object must be passed to SvObject, because otherwise itself will
259 * create and define an IUnknown, so that all other I... objects would be
260 * destroyed with delete (Owner() == true).
261 * But IStorage objects are only used and not implemented by ourselves,
262 * therefore we pretend the IStorage object was passed from the outside
263 * and it will be freed with Release().
264 * The CreateStorage methods are needed to create an IStorage object before the
265 * call of SvObject (Own, !Own automatic).
266 * If CreateStorage has created an object, then the RefCounter was already
267 * incremented.
268 * The transfer is done in pStorageCTor and the variable is NULL, if it didn't
269 * work.
271 #define INIT_SotStorage() \
272 : m_pOwnStg( nullptr ) \
273 , m_pStorStm( nullptr ) \
274 , m_nError( ERRCODE_NONE ) \
275 , m_bIsRoot( false ) \
276 , m_bDelStm( false ) \
277 , m_nVersion( SOFFICE_FILEFORMAT_CURRENT )
279 #define ERASEMASK ( StreamMode::TRUNC | StreamMode::WRITE | StreamMode::SHARE_DENYALL )
281 SotStorage::SotStorage( const OUString & rName, StreamMode nMode )
282 INIT_SotStorage()
284 m_aName = rName; // save name
285 CreateStorage( true, nMode );
286 if ( IsOLEStorage() )
287 m_nVersion = SOFFICE_FILEFORMAT_50;
290 void SotStorage::CreateStorage( bool bForceUCBStorage, StreamMode nMode )
292 DBG_ASSERT( !m_pStorStm && !m_pOwnStg, "Use only in ctor!" );
293 if( !m_aName.isEmpty() )
295 // named storage
296 if( ( nMode & ERASEMASK ) == ERASEMASK )
297 ::utl::UCBContentHelper::Kill( m_aName );
299 INetURLObject aObj( m_aName );
300 if ( aObj.GetProtocol() == INetProtocol::NotValid )
302 OUString aURL;
303 osl::FileBase::getFileURLFromSystemPath( m_aName, aURL );
304 aObj.SetURL( aURL );
305 m_aName = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
308 // check the stream
309 m_pStorStm = ::utl::UcbStreamHelper::CreateStream( m_aName, nMode ).release();
310 if ( m_pStorStm && m_pStorStm->GetError() )
311 DELETEZ( m_pStorStm );
313 if ( m_pStorStm )
315 // try as UCBStorage, next try as OLEStorage
316 bool bIsUCBStorage = UCBStorage::IsStorageFile( m_pStorStm );
317 if ( !bIsUCBStorage && bForceUCBStorage )
318 // if UCBStorage has priority, it should not be used only if it is really an OLEStorage
319 bIsUCBStorage = !Storage::IsStorageFile( m_pStorStm );
321 if ( bIsUCBStorage )
323 if ( !(UCBStorage::GetLinkedFile( *m_pStorStm ).isEmpty()) )
325 // detect special unpacked storages
326 m_pOwnStg = new UCBStorage( *m_pStorStm, true );
327 m_bDelStm = true;
329 else
331 // UCBStorage always works directly on the UCB content, so discard the stream first
332 DELETEZ( m_pStorStm );
333 m_pOwnStg = new UCBStorage( m_aName, nMode, true, true/*bIsRoot*/ );
336 else
338 // OLEStorage can be opened with a stream
339 m_pOwnStg = new Storage( *m_pStorStm, true );
340 m_bDelStm = true;
343 else if ( bForceUCBStorage )
345 m_pOwnStg = new UCBStorage( m_aName, nMode, true, true/*bIsRoot*/ );
346 SetError( ERRCODE_IO_NOTSUPPORTED );
348 else
350 m_pOwnStg = new Storage( m_aName, nMode, true );
351 SetError( ERRCODE_IO_NOTSUPPORTED );
354 else
356 // temporary storage
357 if ( bForceUCBStorage )
358 m_pOwnStg = new UCBStorage( m_aName, nMode, true, true/*bIsRoot*/ );
359 else
360 m_pOwnStg = new Storage( m_aName, nMode, true );
361 m_aName = m_pOwnStg->GetName();
364 SetError( m_pOwnStg->GetError() );
366 SignAsRoot( m_pOwnStg->IsRoot() );
369 SotStorage::SotStorage( bool bUCBStorage, const OUString & rName, StreamMode nMode )
370 INIT_SotStorage()
372 m_aName = rName;
373 CreateStorage( bUCBStorage, nMode );
374 if ( IsOLEStorage() )
375 m_nVersion = SOFFICE_FILEFORMAT_50;
378 SotStorage::SotStorage( BaseStorage * pStor )
379 INIT_SotStorage()
381 if ( pStor )
383 m_aName = pStor->GetName(); // save name
384 SignAsRoot( pStor->IsRoot() );
385 SetError( pStor->GetError() );
388 m_pOwnStg = pStor;
389 const ErrCode nErr = m_pOwnStg ? m_pOwnStg->GetError() : SVSTREAM_CANNOT_MAKE;
390 SetError( nErr );
391 if ( IsOLEStorage() )
392 m_nVersion = SOFFICE_FILEFORMAT_50;
395 SotStorage::SotStorage( bool bUCBStorage, SvStream & rStm )
396 INIT_SotStorage()
398 SetError( rStm.GetError() );
400 // try as UCBStorage, next try as OLEStorage
401 if ( UCBStorage::IsStorageFile( &rStm ) || bUCBStorage )
402 m_pOwnStg = new UCBStorage( rStm, false );
403 else
404 m_pOwnStg = new Storage( rStm, false );
406 SetError( m_pOwnStg->GetError() );
408 if ( IsOLEStorage() )
409 m_nVersion = SOFFICE_FILEFORMAT_50;
411 SignAsRoot( m_pOwnStg->IsRoot() );
414 SotStorage::SotStorage( SvStream & rStm )
415 INIT_SotStorage()
417 SetError( rStm.GetError() );
419 // try as UCBStorage, next try as OLEStorage
420 if ( UCBStorage::IsStorageFile( &rStm ) )
421 m_pOwnStg = new UCBStorage( rStm, false );
422 else
423 m_pOwnStg = new Storage( rStm, false );
425 SetError( m_pOwnStg->GetError() );
427 if ( IsOLEStorage() )
428 m_nVersion = SOFFICE_FILEFORMAT_50;
430 SignAsRoot( m_pOwnStg->IsRoot() );
433 SotStorage::SotStorage( SvStream * pStm, bool bDelete )
434 INIT_SotStorage()
436 SetError( pStm->GetError() );
438 // try as UCBStorage, next try as OLEStorage
439 if ( UCBStorage::IsStorageFile( pStm ) )
440 m_pOwnStg = new UCBStorage( *pStm, false );
441 else
442 m_pOwnStg = new Storage( *pStm, false );
444 SetError( m_pOwnStg->GetError() );
446 m_pStorStm = pStm;
447 m_bDelStm = bDelete;
448 if ( IsOLEStorage() )
449 m_nVersion = SOFFICE_FILEFORMAT_50;
451 SignAsRoot( m_pOwnStg->IsRoot() );
454 SotStorage::~SotStorage()
456 delete m_pOwnStg;
457 if( m_bDelStm )
458 delete m_pStorStm;
461 std::unique_ptr<SvMemoryStream> SotStorage::CreateMemoryStream()
463 std::unique_ptr<SvMemoryStream> pStm(new SvMemoryStream( 0x8000, 0x8000 ));
464 tools::SvRef<SotStorage> aStg = new SotStorage( *pStm );
465 if( CopyTo( aStg.get() ) )
467 aStg->Commit();
469 else
471 aStg.clear(); // release storage beforehand
472 pStm.reset();
474 return pStm;
477 bool SotStorage::IsStorageFile( const OUString & rFileName )
479 OUString aName( rFileName );
480 INetURLObject aObj( aName );
481 if ( aObj.GetProtocol() == INetProtocol::NotValid )
483 OUString aURL;
484 osl::FileBase::getFileURLFromSystemPath( aName, aURL );
485 aObj.SetURL( aURL );
486 aName = aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
489 std::unique_ptr<SvStream> pStm(::utl::UcbStreamHelper::CreateStream( aName, StreamMode::STD_READ ));
490 bool bRet = SotStorage::IsStorageFile( pStm.get() );
491 return bRet;
494 bool SotStorage::IsStorageFile( SvStream* pStream )
496 /** code for new storages must come first! **/
497 if ( pStream )
499 sal_uInt64 nPos = pStream->Tell();
500 bool bRet = UCBStorage::IsStorageFile( pStream );
501 if ( !bRet )
502 bRet = Storage::IsStorageFile( pStream );
503 pStream->Seek( nPos );
504 return bRet;
506 else
507 return false;
510 const OUString & SotStorage::GetName() const
512 if( m_aName.isEmpty() && m_pOwnStg )
513 const_cast<SotStorage *>(this)->m_aName = m_pOwnStg->GetName();
514 return m_aName;
517 void SotStorage::SetClass( const SvGlobalName & rName,
518 SotClipboardFormatId nOriginalClipFormat,
519 const OUString & rUserTypeName )
521 if( m_pOwnStg )
522 m_pOwnStg->SetClass( rName, nOriginalClipFormat, rUserTypeName );
523 else
524 SetError( SVSTREAM_GENERALERROR );
527 SvGlobalName SotStorage::GetClassName()
529 SvGlobalName aGN;
530 if( m_pOwnStg )
531 aGN = m_pOwnStg->GetClassName();
532 else
533 SetError( SVSTREAM_GENERALERROR );
534 return aGN;
537 SotClipboardFormatId SotStorage::GetFormat()
539 SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
540 if( m_pOwnStg )
541 nFormat = m_pOwnStg->GetFormat();
542 else
543 SetError( SVSTREAM_GENERALERROR );
544 return nFormat;
547 OUString SotStorage::GetUserName()
549 OUString aName;
550 if( m_pOwnStg )
551 aName = m_pOwnStg->GetUserName();
552 else
553 SetError( SVSTREAM_GENERALERROR );
554 return aName;
557 void SotStorage::FillInfoList( SvStorageInfoList * pFillList ) const
559 if( m_pOwnStg )
560 m_pOwnStg->FillInfoList( pFillList );
563 bool SotStorage::CopyTo( SotStorage * pDestStg )
565 if( m_pOwnStg && pDestStg->m_pOwnStg )
567 m_pOwnStg->CopyTo( pDestStg->m_pOwnStg );
568 SetError( m_pOwnStg->GetError() );
569 pDestStg->m_aKey = m_aKey;
570 pDestStg->m_nVersion = m_nVersion;
572 else
573 SetError( SVSTREAM_GENERALERROR );
575 return ERRCODE_NONE == GetError();
578 bool SotStorage::Commit()
580 if( m_pOwnStg )
582 if( !m_pOwnStg->Commit() )
583 SetError( m_pOwnStg->GetError() );
585 else
586 SetError( SVSTREAM_GENERALERROR );
588 return ERRCODE_NONE == GetError();
591 SotStorageStream * SotStorage::OpenSotStream( const OUString & rEleName,
592 StreamMode nMode )
594 SotStorageStream * pStm = nullptr;
595 if( m_pOwnStg )
597 // enable full Ole patches,
598 // regardless what is coming, only exclusively allowed
599 nMode |= StreamMode::SHARE_DENYALL;
600 ErrCode nE = m_pOwnStg->GetError();
601 BaseStorageStream * p = m_pOwnStg->OpenStream( rEleName, nMode );
602 pStm = new SotStorageStream( p );
604 if( !nE )
605 m_pOwnStg->ResetError(); // don't set error
606 if( nMode & StreamMode::TRUNC )
607 pStm->SetSize( 0 );
609 else
610 SetError( SVSTREAM_GENERALERROR );
612 return pStm;
615 SotStorage * SotStorage::OpenSotStorage( const OUString & rEleName,
616 StreamMode nMode,
617 bool transacted )
619 if( m_pOwnStg )
621 nMode |= StreamMode::SHARE_DENYALL;
622 ErrCode nE = m_pOwnStg->GetError();
623 BaseStorage * p = m_pOwnStg->OpenStorage(rEleName, nMode, !transacted);
624 if( p )
626 SotStorage * pStor = new SotStorage( p );
627 if( !nE )
628 m_pOwnStg->ResetError(); // don't set error
630 return pStor;
634 SetError( SVSTREAM_GENERALERROR );
636 return nullptr;
639 bool SotStorage::IsStorage( const OUString & rEleName ) const
641 // a little bit faster
642 if( m_pOwnStg )
643 return m_pOwnStg->IsStorage( rEleName );
645 return false;
648 bool SotStorage::IsStream( const OUString & rEleName ) const
650 // a little bit faster
651 if( m_pOwnStg )
652 return m_pOwnStg->IsStream( rEleName );
654 return false;
657 bool SotStorage::IsContained( const OUString & rEleName ) const
659 // a little bit faster
660 if( m_pOwnStg )
661 return m_pOwnStg->IsContained( rEleName );
663 return false;
666 bool SotStorage::Remove( const OUString & rEleName )
668 if( m_pOwnStg )
670 m_pOwnStg->Remove( rEleName );
671 SetError( m_pOwnStg->GetError() );
673 else
674 SetError( SVSTREAM_GENERALERROR );
676 return ERRCODE_NONE == GetError();
679 bool SotStorage::CopyTo( const OUString & rEleName,
680 SotStorage * pNewSt, const OUString & rNewName )
682 if( m_pOwnStg )
684 m_pOwnStg->CopyTo( rEleName, pNewSt->m_pOwnStg, rNewName );
685 SetError( m_pOwnStg->GetError() );
686 SetError( pNewSt->GetError() );
688 else
689 SetError( SVSTREAM_GENERALERROR );
691 return ERRCODE_NONE == GetError();
694 bool SotStorage::Validate()
696 DBG_ASSERT( m_bIsRoot, "Validate only if root storage" );
697 if( m_pOwnStg )
698 return m_pOwnStg->ValidateFAT();
699 else
700 return true;
703 bool SotStorage::IsOLEStorage() const
705 UCBStorage* pStg = dynamic_cast<UCBStorage*>( m_pOwnStg );
706 return !pStg;
709 bool SotStorage::IsOLEStorage( const OUString & rFileName )
711 return Storage::IsStorageFile( rFileName );
714 bool SotStorage::IsOLEStorage( SvStream* pStream )
716 return Storage::IsStorageFile( pStream );
719 SotStorage* SotStorage::OpenOLEStorage( const css::uno::Reference < css::embed::XStorage >& xStorage,
720 const OUString& rEleName, StreamMode nMode )
722 sal_Int32 nEleMode = embed::ElementModes::SEEKABLEREAD;
723 if ( nMode & StreamMode::WRITE )
724 nEleMode |= embed::ElementModes::WRITE;
725 if ( nMode & StreamMode::TRUNC )
726 nEleMode |= embed::ElementModes::TRUNCATE;
727 if ( nMode & StreamMode::NOCREATE )
728 nEleMode |= embed::ElementModes::NOCREATE;
730 std::unique_ptr<SvStream> pStream;
733 uno::Reference < io::XStream > xStream = xStorage->openStreamElement( rEleName, nEleMode );
735 // TODO/LATER: should it be done this way?
736 if ( nMode & StreamMode::WRITE )
738 uno::Reference < beans::XPropertySet > xStreamProps( xStream, uno::UNO_QUERY_THROW );
739 xStreamProps->setPropertyValue( "MediaType",
740 uno::makeAny( OUString( "application/vnd.sun.star.oleobject" ) ) );
743 pStream = utl::UcbStreamHelper::CreateStream( xStream );
745 catch ( uno::Exception& )
747 //TODO/LATER: ErrorHandling
748 pStream.reset( new SvMemoryStream );
749 pStream->SetError( ERRCODE_IO_GENERAL );
752 return new SotStorage( pStream.release(), true );
755 SotClipboardFormatId SotStorage::GetFormatID( const css::uno::Reference < css::embed::XStorage >& xStorage )
757 uno::Reference< beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY );
758 if ( !xProps.is() )
759 return SotClipboardFormatId::NONE;
761 OUString aMediaType;
764 xProps->getPropertyValue("MediaType") >>= aMediaType;
766 catch (uno::Exception const& e)
768 SAL_INFO("sot", "SotStorage::GetFormatID: exception: " << e);
771 if ( !aMediaType.isEmpty() )
773 css::datatransfer::DataFlavor aDataFlavor;
774 aDataFlavor.MimeType = aMediaType;
775 return SotExchange::GetFormat( aDataFlavor );
778 return SotClipboardFormatId::NONE;
781 sal_Int32 SotStorage::GetVersion( const css::uno::Reference < css::embed::XStorage >& xStorage )
783 SotClipboardFormatId nSotFormatID = SotStorage::GetFormatID( xStorage );
784 switch( nSotFormatID )
786 case SotClipboardFormatId::STARWRITER_8:
787 case SotClipboardFormatId::STARWRITER_8_TEMPLATE:
788 case SotClipboardFormatId::STARWRITERWEB_8:
789 case SotClipboardFormatId::STARWRITERGLOB_8:
790 case SotClipboardFormatId::STARWRITERGLOB_8_TEMPLATE:
791 case SotClipboardFormatId::STARDRAW_8:
792 case SotClipboardFormatId::STARDRAW_8_TEMPLATE:
793 case SotClipboardFormatId::STARIMPRESS_8:
794 case SotClipboardFormatId::STARIMPRESS_8_TEMPLATE:
795 case SotClipboardFormatId::STARCALC_8:
796 case SotClipboardFormatId::STARCALC_8_TEMPLATE:
797 case SotClipboardFormatId::STARCHART_8:
798 case SotClipboardFormatId::STARCHART_8_TEMPLATE:
799 case SotClipboardFormatId::STARMATH_8:
800 case SotClipboardFormatId::STARMATH_8_TEMPLATE:
801 return SOFFICE_FILEFORMAT_8;
802 case SotClipboardFormatId::STARWRITER_60:
803 case SotClipboardFormatId::STARWRITERWEB_60:
804 case SotClipboardFormatId::STARWRITERGLOB_60:
805 case SotClipboardFormatId::STARDRAW_60:
806 case SotClipboardFormatId::STARIMPRESS_60:
807 case SotClipboardFormatId::STARCALC_60:
808 case SotClipboardFormatId::STARCHART_60:
809 case SotClipboardFormatId::STARMATH_60:
810 return SOFFICE_FILEFORMAT_60;
811 default: break;
814 return 0;
817 namespace
819 void traverse(const tools::SvRef<SotStorage>& rStorage, std::vector<unsigned char>& rBuf)
821 SvStorageInfoList infos;
823 rStorage->FillInfoList(&infos);
825 for (const auto& info: infos)
827 if (info.IsStream())
829 // try to open and read all content
830 tools::SvRef<SotStorageStream> xStream(rStorage->OpenSotStream(info.GetName(), StreamMode::STD_READ));
831 const size_t nSize = xStream->GetSize();
832 const size_t nRead = xStream->ReadBytes(rBuf.data(), nSize);
833 SAL_INFO("sot", "Read " << nRead << "bytes");
835 else if (info.IsStorage())
837 tools::SvRef<SotStorage> xStorage(rStorage->OpenSotStorage(info.GetName(), StreamMode::STD_READ));
839 // continue with children
840 traverse(xStorage, rBuf);
846 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportOLE2(SvStream &rStream)
850 size_t nSize = rStream.remainingSize();
851 tools::SvRef<SotStorage> xRootStorage(new SotStorage(&rStream, false));
852 std::vector<unsigned char> aTmpBuf(nSize);
853 traverse(xRootStorage, aTmpBuf);
855 catch (...)
857 return false;
859 return true;
862 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */