LCOV - code coverage report
Current view: top level - sot/source/sdstor - ucbstorage.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 159 1401 11.3 %
Date: 2015-06-13 12:38:46 Functions: 23 137 16.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <com/sun/star/io/NotConnectedException.hpp>
      21             : #include <com/sun/star/io/BufferSizeExceededException.hpp>
      22             : #include <com/sun/star/uno/RuntimeException.hpp>
      23             : #include <com/sun/star/lang/IllegalArgumentException.hpp>
      24             : #include <ucbhelper/content.hxx>
      25             : #include <com/sun/star/uno/Reference.h>
      26             : #include <com/sun/star/ucb/NameClash.hpp>
      27             : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
      28             : #include <unotools/tempfile.hxx>
      29             : #include <unotools/ucbstreamhelper.hxx>
      30             : #include <com/sun/star/io/XInputStream.hpp>
      31             : #include <com/sun/star/ucb/InsertCommandArgument.hpp>
      32             : #include <com/sun/star/ucb/ResultSetException.hpp>
      33             : #include <com/sun/star/uno/Sequence.h>
      34             : #include <com/sun/star/sdbc/XResultSet.hpp>
      35             : #include <com/sun/star/ucb/XContentAccess.hpp>
      36             : #include <com/sun/star/sdbc/XRow.hpp>
      37             : #include <com/sun/star/ucb/CommandAbortedException.hpp>
      38             : #include <com/sun/star/datatransfer/DataFlavor.hpp>
      39             : #include <com/sun/star/ucb/ContentInfo.hpp>
      40             : #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
      41             : #include <com/sun/star/beans/Property.hpp>
      42             : #include <com/sun/star/packages/manifest/ManifestWriter.hpp>
      43             : #include <com/sun/star/packages/manifest/ManifestReader.hpp>
      44             : #include <com/sun/star/ucb/InteractiveIOException.hpp>
      45             : 
      46             : #include <boost/scoped_array.hpp>
      47             : #include <boost/scoped_ptr.hpp>
      48             : #include <rtl/digest.h>
      49             : #include <osl/diagnose.h>
      50             : #include <tools/ref.hxx>
      51             : #include <tools/debug.hxx>
      52             : #include <unotools/streamhelper.hxx>
      53             : #include <unotools/streamwrap.hxx>
      54             : #include <unotools/ucbhelper.hxx>
      55             : #include <unotools/localfilehelper.hxx>
      56             : #include <tools/urlobj.hxx>
      57             : #include <comphelper/processfactory.hxx>
      58             : #include <cppuhelper/implbase2.hxx>
      59             : #include <ucbhelper/commandenvironment.hxx>
      60             : 
      61             : #include "sot/stg.hxx"
      62             : #include "sot/storinfo.hxx"
      63             : #include <sot/storage.hxx>
      64             : #include <sot/exchange.hxx>
      65             : #include <sot/formats.hxx>
      66             : #include <comphelper/classids.hxx>
      67             : 
      68             : #include <vector>
      69             : 
      70             : using namespace ::com::sun::star::lang;
      71             : using namespace ::com::sun::star::beans;
      72             : using namespace ::com::sun::star::uno;
      73             : using namespace ::com::sun::star::ucb;
      74             : using namespace ::com::sun::star::io;
      75             : using namespace ::com::sun::star::sdbc;
      76             : using namespace ::ucbhelper;
      77             : 
      78             : #if OSL_DEBUG_LEVEL > 1
      79             : #include <stdio.h>
      80             : static int nOpenFiles=0;
      81             : static int nOpenStreams=0;
      82             : #endif
      83             : 
      84             : typedef ::cppu::WeakImplHelper2 < XInputStream, XSeekable > FileInputStreamWrapper_Base;
      85             : class FileStreamWrapper_Impl : public FileInputStreamWrapper_Base
      86             : {
      87             : protected:
      88             :     ::osl::Mutex    m_aMutex;
      89             :     OUString        m_aURL;
      90             :     SvStream*       m_pSvStream;
      91             : 
      92             : public:
      93             :     FileStreamWrapper_Impl( const OUString& rName );
      94             :     virtual ~FileStreamWrapper_Impl();
      95             : 
      96             :     virtual void SAL_CALL seek( sal_Int64 _nLocation ) throw ( IllegalArgumentException, IOException, RuntimeException, std::exception) SAL_OVERRIDE;
      97             :     virtual sal_Int64 SAL_CALL getPosition(  ) throw ( IOException, RuntimeException, std::exception) SAL_OVERRIDE;
      98             :     virtual sal_Int64 SAL_CALL getLength(  ) throw ( IOException, RuntimeException, std::exception) SAL_OVERRIDE;
      99             :     virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception ) SAL_OVERRIDE;
     100             :     virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception ) SAL_OVERRIDE;
     101             :     virtual void      SAL_CALL skipBytes(sal_Int32 nBytesToSkip) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception) SAL_OVERRIDE;
     102             :     virtual sal_Int32 SAL_CALL available() throw( NotConnectedException, RuntimeException, std::exception ) SAL_OVERRIDE;
     103             :     virtual void      SAL_CALL closeInput() throw( NotConnectedException, RuntimeException, std::exception ) SAL_OVERRIDE;
     104             : 
     105             : protected:
     106             :     void checkConnected();
     107             :     void checkError();
     108             : };
     109             : 
     110             : 
     111           0 : FileStreamWrapper_Impl::FileStreamWrapper_Impl( const OUString& rName )
     112             :     : m_aURL( rName )
     113           0 :     , m_pSvStream(0)
     114             : {
     115             :     // if no URL is provided the stream is empty
     116           0 : }
     117             : 
     118             : 
     119           0 : FileStreamWrapper_Impl::~FileStreamWrapper_Impl()
     120             : {
     121           0 :     if ( m_pSvStream )
     122             :     {
     123           0 :         delete m_pSvStream;
     124             : #if OSL_DEBUG_LEVEL > 1
     125             :         --nOpenFiles;
     126             : #endif
     127             :     }
     128             : 
     129           0 :     if ( !m_aURL.isEmpty() )
     130           0 :         ::utl::UCBContentHelper::Kill( m_aURL );
     131           0 : }
     132             : 
     133             : 
     134           0 : sal_Int32 SAL_CALL FileStreamWrapper_Impl::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
     135             :                 throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception )
     136             : {
     137           0 :     if ( m_aURL.isEmpty() )
     138             :     {
     139           0 :         aData.realloc( 0 );
     140           0 :         return 0;
     141             :     }
     142             : 
     143           0 :     checkConnected();
     144             : 
     145           0 :     if (nBytesToRead < 0)
     146           0 :         throw BufferSizeExceededException(OUString(),static_cast<XWeak*>(this));
     147             : 
     148           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     149             : 
     150           0 :     aData.realloc(nBytesToRead);
     151             : 
     152           0 :     sal_uInt32 nRead = m_pSvStream->Read(static_cast<void*>(aData.getArray()), nBytesToRead);
     153           0 :     checkError();
     154             : 
     155             :     // Wenn gelesene Zeichen < MaxLength, Sequence anpassen
     156           0 :     if (nRead < (sal_uInt32)nBytesToRead)
     157           0 :         aData.realloc( nRead );
     158             : 
     159           0 :     return nRead;
     160             : }
     161             : 
     162             : 
     163           0 : sal_Int32 SAL_CALL FileStreamWrapper_Impl::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception )
     164             : {
     165           0 :     if ( m_aURL.isEmpty() )
     166             :     {
     167           0 :         aData.realloc( 0 );
     168           0 :         return 0;
     169             :     }
     170             : 
     171           0 :     checkError();
     172             : 
     173           0 :     if (nMaxBytesToRead < 0)
     174           0 :         throw BufferSizeExceededException(OUString(),static_cast<XWeak*>(this));
     175             : 
     176           0 :     if (m_pSvStream->IsEof())
     177             :     {
     178           0 :         aData.realloc(0);
     179           0 :         return 0;
     180             :     }
     181             :     else
     182           0 :         return readBytes(aData, nMaxBytesToRead);
     183             : }
     184             : 
     185             : 
     186           0 : void SAL_CALL FileStreamWrapper_Impl::skipBytes(sal_Int32 nBytesToSkip) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception )
     187             : {
     188           0 :     if ( m_aURL.isEmpty() )
     189           0 :         return;
     190             : 
     191           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     192           0 :     checkError();
     193             : 
     194           0 :     m_pSvStream->SeekRel(nBytesToSkip);
     195           0 :     checkError();
     196             : }
     197             : 
     198             : 
     199           0 : sal_Int32 SAL_CALL FileStreamWrapper_Impl::available() throw( NotConnectedException, RuntimeException, std::exception )
     200             : {
     201           0 :     if ( m_aURL.isEmpty() )
     202           0 :         return 0;
     203             : 
     204           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     205           0 :     checkConnected();
     206             : 
     207           0 :     sal_uInt32 nPos = m_pSvStream->Tell();
     208           0 :     checkError();
     209             : 
     210           0 :     m_pSvStream->Seek(STREAM_SEEK_TO_END);
     211           0 :     checkError();
     212             : 
     213           0 :     sal_Int32 nAvailable = (sal_Int32)m_pSvStream->Tell() - nPos;
     214           0 :     m_pSvStream->Seek(nPos);
     215           0 :     checkError();
     216             : 
     217           0 :     return nAvailable;
     218             : }
     219             : 
     220             : 
     221           0 : void SAL_CALL FileStreamWrapper_Impl::closeInput() throw( NotConnectedException, RuntimeException, std::exception )
     222             : {
     223           0 :     if ( m_aURL.isEmpty() )
     224           0 :         return;
     225             : 
     226           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     227           0 :     checkConnected();
     228           0 :     DELETEZ( m_pSvStream );
     229             : #if OSL_DEBUG_LEVEL > 1
     230             :     --nOpenFiles;
     231             : #endif
     232           0 :     ::utl::UCBContentHelper::Kill( m_aURL );
     233           0 :     m_aURL.clear();
     234             : }
     235             : 
     236             : 
     237           0 : void SAL_CALL FileStreamWrapper_Impl::seek( sal_Int64 _nLocation ) throw (IllegalArgumentException, IOException, RuntimeException, std::exception)
     238             : {
     239           0 :     if ( m_aURL.isEmpty() )
     240           0 :         return;
     241             : 
     242           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     243           0 :     checkConnected();
     244             : 
     245           0 :     m_pSvStream->Seek((sal_uInt32)_nLocation);
     246           0 :     checkError();
     247             : }
     248             : 
     249             : 
     250           0 : sal_Int64 SAL_CALL FileStreamWrapper_Impl::getPosition(  ) throw (IOException, RuntimeException, std::exception)
     251             : {
     252           0 :     if ( m_aURL.isEmpty() )
     253           0 :         return 0;
     254             : 
     255           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     256           0 :     checkConnected();
     257             : 
     258           0 :     sal_uInt32 nPos = m_pSvStream->Tell();
     259           0 :     checkError();
     260           0 :     return (sal_Int64)nPos;
     261             : }
     262             : 
     263             : 
     264           0 : sal_Int64 SAL_CALL FileStreamWrapper_Impl::getLength(  ) throw (IOException, RuntimeException, std::exception)
     265             : {
     266           0 :     if ( m_aURL.isEmpty() )
     267           0 :         return 0;
     268             : 
     269           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     270           0 :     checkConnected();
     271             : 
     272           0 :     sal_uInt32 nCurrentPos = m_pSvStream->Tell();
     273           0 :     checkError();
     274             : 
     275           0 :     m_pSvStream->Seek(STREAM_SEEK_TO_END);
     276           0 :     sal_uInt32 nEndPos = m_pSvStream->Tell();
     277           0 :     m_pSvStream->Seek(nCurrentPos);
     278             : 
     279           0 :     checkError();
     280             : 
     281           0 :     return (sal_Int64)nEndPos;
     282             : }
     283             : 
     284             : 
     285           0 : void FileStreamWrapper_Impl::checkConnected()
     286             : {
     287           0 :     if ( m_aURL.isEmpty() )
     288           0 :         throw NotConnectedException(OUString(), const_cast<XWeak*>(static_cast<const XWeak*>(this)));
     289           0 :     if ( !m_pSvStream )
     290             :     {
     291           0 :         m_pSvStream = ::utl::UcbStreamHelper::CreateStream( m_aURL, STREAM_STD_READ );
     292             : #if OSL_DEBUG_LEVEL > 1
     293             :         ++nOpenFiles;
     294             : #endif
     295             :     }
     296           0 : }
     297             : 
     298             : 
     299           0 : void FileStreamWrapper_Impl::checkError()
     300             : {
     301           0 :     checkConnected();
     302             : 
     303           0 :     if (m_pSvStream->SvStream::GetError() != ERRCODE_NONE)
     304             :         // TODO: really evaluate the error
     305           0 :         throw NotConnectedException(OUString(), const_cast<XWeak*>(static_cast<const XWeak*>(this)));
     306           0 : }
     307             : 
     308           0 : TYPEINIT1( UCBStorageStream, BaseStorageStream );
     309       10157 : TYPEINIT1( UCBStorage, BaseStorage );
     310             : 
     311             : #define COMMIT_RESULT_FAILURE           0
     312             : #define COMMIT_RESULT_NOTHING_TO_DO     1
     313             : #define COMMIT_RESULT_SUCCESS           2
     314             : 
     315             : #define min( x, y ) (( x < y ) ? x : y)
     316             : 
     317           0 : SotClipboardFormatId GetFormatId_Impl( SvGlobalName aName )
     318             : {
     319           0 :     if ( aName == SvGlobalName( SO3_SW_CLASSID_60 ) )
     320           0 :         return SotClipboardFormatId::STARWRITER_60;
     321           0 :     if ( aName == SvGlobalName( SO3_SWWEB_CLASSID_60 ) )
     322           0 :         return SotClipboardFormatId::STARWRITERWEB_60;
     323           0 :     if ( aName == SvGlobalName( SO3_SWGLOB_CLASSID_60 ) )
     324           0 :         return SotClipboardFormatId::STARWRITERGLOB_60;
     325           0 :     if ( aName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) )
     326           0 :         return SotClipboardFormatId::STARDRAW_60;
     327           0 :     if ( aName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) )
     328           0 :         return SotClipboardFormatId::STARIMPRESS_60;
     329           0 :     if ( aName == SvGlobalName( SO3_SC_CLASSID_60 ) )
     330           0 :         return SotClipboardFormatId::STARCALC_60;
     331           0 :     if ( aName == SvGlobalName( SO3_SCH_CLASSID_60 ) )
     332           0 :         return SotClipboardFormatId::STARCHART_60;
     333           0 :     if ( aName == SvGlobalName( SO3_SM_CLASSID_60 ) )
     334           0 :         return SotClipboardFormatId::STARMATH_60;
     335           0 :     if ( aName == SvGlobalName( SO3_OUT_CLASSID ) ||
     336           0 :          aName == SvGlobalName( SO3_APPLET_CLASSID ) ||
     337           0 :          aName == SvGlobalName( SO3_PLUGIN_CLASSID ) ||
     338           0 :          aName == SvGlobalName( SO3_IFRAME_CLASSID ) )
     339             :         // allowed, but not supported
     340           0 :         return SotClipboardFormatId::NONE;
     341             :     else
     342             :     {
     343             :         OSL_FAIL( "Unknown UCB storage format!" );
     344           0 :         return SotClipboardFormatId::NONE;
     345             :     }
     346             : }
     347             : 
     348             : 
     349           0 : SvGlobalName GetClassId_Impl( SotClipboardFormatId nFormat )
     350             : {
     351           0 :     switch ( nFormat )
     352             :     {
     353             :         case SotClipboardFormatId::STARWRITER_8 :
     354             :         case SotClipboardFormatId::STARWRITER_8_TEMPLATE :
     355           0 :             return SvGlobalName( SO3_SW_CLASSID_60 );
     356             :         case SotClipboardFormatId::STARWRITERWEB_8 :
     357           0 :             return SvGlobalName( SO3_SWWEB_CLASSID_60 );
     358             :         case SotClipboardFormatId::STARWRITERGLOB_8 :
     359             :         case SotClipboardFormatId::STARWRITERGLOB_8_TEMPLATE :
     360           0 :             return SvGlobalName( SO3_SWGLOB_CLASSID_60 );
     361             :         case SotClipboardFormatId::STARDRAW_8 :
     362             :         case SotClipboardFormatId::STARDRAW_8_TEMPLATE :
     363           0 :             return SvGlobalName( SO3_SDRAW_CLASSID_60 );
     364             :         case SotClipboardFormatId::STARIMPRESS_8 :
     365             :         case SotClipboardFormatId::STARIMPRESS_8_TEMPLATE :
     366           0 :             return SvGlobalName( SO3_SIMPRESS_CLASSID_60 );
     367             :         case SotClipboardFormatId::STARCALC_8 :
     368             :         case SotClipboardFormatId::STARCALC_8_TEMPLATE :
     369           0 :             return SvGlobalName( SO3_SC_CLASSID_60 );
     370             :         case SotClipboardFormatId::STARCHART_8 :
     371             :         case SotClipboardFormatId::STARCHART_8_TEMPLATE :
     372           0 :             return SvGlobalName( SO3_SCH_CLASSID_60 );
     373             :         case SotClipboardFormatId::STARMATH_8 :
     374             :         case SotClipboardFormatId::STARMATH_8_TEMPLATE :
     375           0 :             return SvGlobalName( SO3_SM_CLASSID_60 );
     376             :         case SotClipboardFormatId::STARWRITER_60 :
     377           0 :             return SvGlobalName( SO3_SW_CLASSID_60 );
     378             :         case SotClipboardFormatId::STARWRITERWEB_60 :
     379           0 :             return SvGlobalName( SO3_SWWEB_CLASSID_60 );
     380             :         case SotClipboardFormatId::STARWRITERGLOB_60 :
     381           0 :             return SvGlobalName( SO3_SWGLOB_CLASSID_60 );
     382             :         case SotClipboardFormatId::STARDRAW_60 :
     383           0 :             return SvGlobalName( SO3_SDRAW_CLASSID_60 );
     384             :         case SotClipboardFormatId::STARIMPRESS_60 :
     385           0 :             return SvGlobalName( SO3_SIMPRESS_CLASSID_60 );
     386             :         case SotClipboardFormatId::STARCALC_60 :
     387           0 :             return SvGlobalName( SO3_SC_CLASSID_60 );
     388             :         case SotClipboardFormatId::STARCHART_60 :
     389           0 :             return SvGlobalName( SO3_SCH_CLASSID_60 );
     390             :         case SotClipboardFormatId::STARMATH_60 :
     391           0 :             return SvGlobalName( SO3_SM_CLASSID_60 );
     392             :         default :
     393           0 :             return SvGlobalName();
     394             :     }
     395             : }
     396             : 
     397             : // All storage and streams are refcounted internally; outside of this classes they are only accessible through a handle
     398             : // class, that uses the refcounted object as impl-class.
     399             : 
     400             : enum RepresentModes {
     401             :         nonset,
     402             :         svstream,
     403             :         xinputstream
     404             : };
     405             : 
     406             : class UCBStorageStream_Impl : public SvRefBase, public SvStream
     407             : {
     408             :                                 virtual ~UCBStorageStream_Impl();
     409             : public:
     410             : 
     411             :     virtual sal_uLong           GetData( void* pData, sal_uLong nSize ) SAL_OVERRIDE;
     412             :     virtual sal_uLong           PutData( const void* pData, sal_uLong nSize ) SAL_OVERRIDE;
     413             :     virtual sal_uInt64          SeekPos( sal_uInt64 nPos ) SAL_OVERRIDE;
     414             :     virtual void                SetSize( sal_uInt64 nSize ) SAL_OVERRIDE;
     415             :     virtual void                FlushData() SAL_OVERRIDE;
     416             :     virtual void                ResetError() SAL_OVERRIDE;
     417             : 
     418             :     UCBStorageStream*           m_pAntiImpl;    // only valid if an external reference exists
     419             : 
     420             :     OUString                    m_aOriginalName;// the original name before accessing the stream
     421             :     OUString                    m_aName;        // the actual name ( changed with a Rename command at the parent )
     422             :     OUString                    m_aURL;         // the full path name to create the content
     423             :     OUString                    m_aContentType;
     424             :     OUString                    m_aOriginalContentType;
     425             :     OString                     m_aKey;
     426             :     ::ucbhelper::Content*       m_pContent;     // the content that provides the data
     427             :     Reference<XInputStream>     m_rSource;      // the stream covering the original data of the content
     428             :     SvStream*                   m_pStream;      // the stream worked on; for readonly streams it is the original stream of the content
     429             :                                                 // for read/write streams it's a copy into a temporary file
     430             :     OUString                    m_aTempURL;     // URL of this temporary stream
     431             :     RepresentModes              m_nRepresentMode; // should it be used as XInputStream or as SvStream
     432             :     long                        m_nError;
     433             :     StreamMode                  m_nMode;        // open mode ( read/write/trunc/nocreate/sharing )
     434             :     bool                        m_bSourceRead;  // Source still contains useful information
     435             :     bool                        m_bModified;    // only modified streams will be sent to the original content
     436             :     bool                        m_bCommited;    // sending the streams is coordinated by the root storage of the package
     437             :     bool                        m_bDirect;      // the storage and its streams are opened in direct mode; for UCBStorages
     438             :                                                 // this means that the root storage does an autocommit when its external
     439             :                                                 // reference is destroyed
     440             :     bool                        m_bIsOLEStorage;// an OLEStorage on a UCBStorageStream makes this an Autocommit-stream
     441             : 
     442             :                                 UCBStorageStream_Impl( const OUString&, StreamMode, UCBStorageStream*, bool, const OString* pKey=0,
     443             :                                                        bool bRepair = false, Reference< XProgressHandler > xProgress = Reference< XProgressHandler >() );
     444             : 
     445             :     void                        Free();
     446             :     bool                        Init();
     447             :     bool                        Clear();
     448             :     sal_Int16                   Commit();       // if modified and committed: transfer an XInputStream to the content
     449             :     bool                        Revert();       // discard all changes
     450             :     BaseStorage*                CreateStorage();// create an OLE Storage on the UCBStorageStream
     451             :     sal_uLong                   GetSize();
     452             : 
     453             :     sal_uInt64                   ReadSourceWriteTemporary( sal_uInt64 aLength ); // read aLength from source and copy to temporary,
     454             :                                                                            // no seeking is produced
     455             :     sal_uLong                   ReadSourceWriteTemporary();                // read source till the end and copy to temporary,
     456             : 
     457             :     sal_uLong                   CopySourceToTemporary();                // same as ReadSourceWriteToTemporary()
     458             :                                                                         // but the writing is done at the end of temporary
     459             :                                                                         // pointer position is not changed
     460             :     using SvStream::SetError;
     461             :     void                        SetError( sal_uInt32 nError );
     462             :     void                        PrepareCachedForReopen( StreamMode nMode );
     463             : };
     464             : 
     465             : typedef tools::SvRef<UCBStorageStream_Impl> UCBStorageStream_ImplRef;
     466             : 
     467             : struct UCBStorageElement_Impl;
     468             : typedef ::std::vector< UCBStorageElement_Impl* > UCBStorageElementList_Impl;
     469             : 
     470             : class UCBStorage_Impl : public SvRefBase
     471             : {
     472             :                                 virtual ~UCBStorage_Impl();
     473             : public:
     474             :     UCBStorage*                 m_pAntiImpl;    // only valid if external references exists
     475             : 
     476             :     OUString                    m_aOriginalName;// the original name before accessing the storage
     477             :     OUString                    m_aName;        // the actual name ( changed with a Rename command at the parent )
     478             :     OUString                    m_aURL;         // the full path name to create the content
     479             :     OUString                    m_aContentType;
     480             :     OUString                    m_aOriginalContentType;
     481             :     ::ucbhelper::Content*       m_pContent;     // the content that provides the storage elements
     482             :     ::utl::TempFile*            m_pTempFile;    // temporary file, only for storages on stream
     483             :     SvStream*                   m_pSource;      // original stream, only for storages on a stream
     484             :     long                        m_nError;
     485             :     StreamMode                  m_nMode;        // open mode ( read/write/trunc/nocreate/sharing )
     486             :     bool                        m_bModified;    // only modified elements will be sent to the original content
     487             :     bool                        m_bCommited;    // sending the streams is coordinated by the root storage of the package
     488             :     bool                        m_bDirect;      // the storage and its streams are opened in direct mode; for UCBStorages
     489             :                                                 // this means that the root storage does an autocommit when its external
     490             :                                                 // reference is destroyed
     491             :     bool                        m_bIsRoot;      // marks this storage as root storages that manages all oommits and reverts
     492             :     bool                        m_bDirty;           // ???
     493             :     bool                        m_bIsLinked;
     494             :     bool                        m_bListCreated;
     495             :     SotClipboardFormatId                 m_nFormat;
     496             :     OUString                    m_aUserTypeName;
     497             :     SvGlobalName                m_aClassId;
     498             : 
     499             :     UCBStorageElementList_Impl  m_aChildrenList;
     500             : 
     501             :     bool                        m_bRepairPackage;
     502             :     Reference< XProgressHandler > m_xProgressHandler;
     503             : 
     504             :                                 UCBStorage_Impl( const ::ucbhelper::Content&, const OUString&, StreamMode, UCBStorage*, bool,
     505             :                                                  bool, bool = false, Reference< XProgressHandler > = Reference< XProgressHandler >() );
     506             :                                 UCBStorage_Impl( const OUString&, StreamMode, UCBStorage*, bool, bool,
     507             :                                                  bool = false, Reference< XProgressHandler > = Reference< XProgressHandler >() );
     508             :                                 UCBStorage_Impl( SvStream&, UCBStorage*, bool );
     509             :     void                        Init();
     510             :     sal_Int16                   Commit();
     511             :     bool                        Revert();
     512             :     bool                        Insert( ::ucbhelper::Content *pContent );
     513             :     UCBStorage_Impl*            OpenStorage( UCBStorageElement_Impl* pElement, StreamMode nMode, bool bDirect );
     514             :     UCBStorageStream_Impl*      OpenStream( UCBStorageElement_Impl*, StreamMode, bool, const OString* pKey=0 );
     515             :     void                        SetProps( const Sequence < Sequence < PropertyValue > >& rSequence, const OUString& );
     516             :     void                        GetProps( sal_Int32&, Sequence < Sequence < PropertyValue > >& rSequence, const OUString& );
     517             :     sal_Int32                   GetObjectCount();
     518             :     void                        ReadContent();
     519             :     void                        CreateContent();
     520        2006 :     ::ucbhelper::Content*       GetContent()
     521        2006 :                                 { if ( !m_pContent ) CreateContent(); return m_pContent; }
     522        4012 :     UCBStorageElementList_Impl& GetChildrenList()
     523             :                                 {
     524        4012 :                                   long nError = m_nError;
     525        4012 :                                   ReadContent();
     526        4012 :                                   if ( m_nMode & StreamMode::WRITE )
     527             :                                   {
     528        4012 :                                     m_nError = nError;
     529        4012 :                                     if ( m_pAntiImpl )
     530             :                                     {
     531        4012 :                                         m_pAntiImpl->ResetError();
     532        4012 :                                         m_pAntiImpl->SetError( nError );
     533             :                                     }
     534             :                                   }
     535             : 
     536        4012 :                                   return m_aChildrenList;
     537             :                                 }
     538             : 
     539             :     void                        SetError( long nError );
     540             : };
     541             : 
     542             : typedef tools::SvRef<UCBStorage_Impl> UCBStorage_ImplRef;
     543             : 
     544             : // this struct contains all necessary information on an element inside a UCBStorage
     545           0 : struct UCBStorageElement_Impl
     546             : {
     547             :     OUString                    m_aName;        // the actual URL relative to the root "folder"
     548             :     OUString                    m_aOriginalName;// the original name in the content
     549             :     sal_uLong                   m_nSize;
     550             :     bool                        m_bIsFolder;    // Only true when it is a UCBStorage !
     551             :     bool                        m_bIsStorage;   // Also true when it is an OLEStorage !
     552             :     bool                        m_bIsRemoved;   // element will be removed on commit
     553             :     bool                        m_bIsInserted;  // element will be removed on revert
     554             :     UCBStorage_ImplRef          m_xStorage;     // reference to the "real" storage
     555             :     UCBStorageStream_ImplRef    m_xStream;      // reference to the "real" stream
     556             : 
     557           0 :                                 UCBStorageElement_Impl( const OUString& rName,
     558             :                                                         bool bIsFolder = false, sal_uLong nSize = 0 )
     559             :                                     : m_aName( rName )
     560             :                                     , m_aOriginalName( rName )
     561             :                                     , m_nSize( nSize )
     562             :                                     , m_bIsFolder( bIsFolder )
     563             :                                     , m_bIsStorage( bIsFolder )
     564             :                                     , m_bIsRemoved( false )
     565           0 :                                     , m_bIsInserted( false )
     566             :                                 {
     567           0 :                                 }
     568             : 
     569             :     ::ucbhelper::Content*       GetContent();
     570             :     bool                        IsModified();
     571             :     OUString                    GetContentType();
     572             :     void                        SetContentType( const OUString& );
     573             :     OUString                    GetOriginalContentType();
     574           0 :     bool                        IsLoaded()
     575           0 :                                 { return m_xStream.Is() || m_xStorage.Is(); }
     576             : };
     577             : 
     578           0 : ::ucbhelper::Content* UCBStorageElement_Impl::GetContent()
     579             : {
     580           0 :     if ( m_xStream.Is() )
     581           0 :         return m_xStream->m_pContent;
     582           0 :     else if ( m_xStorage.Is() )
     583           0 :         return m_xStorage->GetContent();
     584             :     else
     585           0 :         return NULL;
     586             : }
     587             : 
     588           0 : OUString UCBStorageElement_Impl::GetContentType()
     589             : {
     590           0 :     if ( m_xStream.Is() )
     591           0 :         return m_xStream->m_aContentType;
     592           0 :     else if ( m_xStorage.Is() )
     593           0 :         return m_xStorage->m_aContentType;
     594             :     else
     595             :     {
     596             :         OSL_FAIL("Element not loaded!");
     597           0 :         return OUString();
     598             :     }
     599             : }
     600             : 
     601           0 : void UCBStorageElement_Impl::SetContentType( const OUString& rType )
     602             : {
     603           0 :     if ( m_xStream.Is() ) {
     604           0 :         m_xStream->m_aContentType = m_xStream->m_aOriginalContentType = rType;
     605             :     }
     606           0 :     else if ( m_xStorage.Is() ) {
     607           0 :         m_xStorage->m_aContentType = m_xStorage->m_aOriginalContentType = rType;
     608             :     }
     609             :     else {
     610             :         OSL_FAIL("Element not loaded!");
     611             :     }
     612           0 : }
     613             : 
     614           0 : OUString UCBStorageElement_Impl::GetOriginalContentType()
     615             : {
     616           0 :     if ( m_xStream.Is() )
     617           0 :         return m_xStream->m_aOriginalContentType;
     618           0 :     else if ( m_xStorage.Is() )
     619           0 :         return m_xStorage->m_aOriginalContentType;
     620             :     else
     621           0 :         return OUString();
     622             : }
     623             : 
     624           0 : bool UCBStorageElement_Impl::IsModified()
     625             : {
     626           0 :     bool bModified = m_bIsRemoved || m_bIsInserted || m_aName != m_aOriginalName;
     627           0 :     if ( bModified )
     628             :     {
     629           0 :         if ( m_xStream.Is() )
     630           0 :             bModified = m_xStream->m_aContentType != m_xStream->m_aOriginalContentType;
     631           0 :         else if ( m_xStorage.Is() )
     632           0 :             bModified = m_xStorage->m_aContentType != m_xStorage->m_aOriginalContentType;
     633             :     }
     634             : 
     635           0 :     return bModified;
     636             : }
     637             : 
     638           0 : UCBStorageStream_Impl::UCBStorageStream_Impl( const OUString& rName, StreamMode nMode, UCBStorageStream* pStream, bool bDirect, const OString* pKey, bool bRepair, Reference< XProgressHandler > xProgress  )
     639             :     : m_pAntiImpl( pStream )
     640             :     , m_aURL( rName )
     641             :     , m_pContent( NULL )
     642             :     , m_pStream( NULL )
     643             :     , m_nRepresentMode( nonset )
     644             :     , m_nError( 0 )
     645             :     , m_nMode( nMode )
     646           0 :     , m_bSourceRead( !( nMode & StreamMode::TRUNC ) )
     647             :     , m_bModified( false )
     648             :     , m_bCommited( false )
     649             :     , m_bDirect( bDirect )
     650           0 :     , m_bIsOLEStorage( false )
     651             : {
     652             :     // name is last segment in URL
     653           0 :     INetURLObject aObj( rName );
     654           0 :     m_aName = m_aOriginalName = aObj.GetLastName();
     655             :     try
     656             :     {
     657             :         // create the content
     658           0 :         Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
     659             : 
     660           0 :         OUString aTemp( rName );
     661             : 
     662           0 :         if ( bRepair )
     663             :         {
     664           0 :             xComEnv = new ::ucbhelper::CommandEnvironment( Reference< ::com::sun::star::task::XInteractionHandler >(),
     665           0 :                                                      xProgress );
     666           0 :             aTemp += "?repairpackage";
     667             :         }
     668             : 
     669           0 :         m_pContent = new ::ucbhelper::Content( aTemp, xComEnv, comphelper::getProcessComponentContext() );
     670             : 
     671           0 :         if ( pKey )
     672             :         {
     673           0 :             m_aKey = *pKey;
     674             : 
     675             :             // stream is encrypted and should be decrypted (without setting the key we'll get the raw data)
     676             :             sal_uInt8 aBuffer[RTL_DIGEST_LENGTH_SHA1];
     677           0 :             rtlDigestError nErr = rtl_digest_SHA1( pKey->getStr(), pKey->getLength(), aBuffer, RTL_DIGEST_LENGTH_SHA1 );
     678           0 :             if ( nErr == rtl_Digest_E_None )
     679             :             {
     680           0 :                 sal_uInt8* pBuffer = aBuffer;
     681           0 :                 ::com::sun::star::uno::Sequence < sal_Int8 > aSequ( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 );
     682           0 :                 ::com::sun::star::uno::Any aAny;
     683           0 :                 aAny <<= aSequ;
     684           0 :                 m_pContent->setPropertyValue("EncryptionKey", aAny );
     685             :             }
     686           0 :         }
     687             :     }
     688           0 :     catch (const ContentCreationException&)
     689             :     {
     690             :         // content could not be created
     691           0 :         SetError( SVSTREAM_CANNOT_MAKE );
     692             :     }
     693           0 :     catch (const RuntimeException&)
     694             :     {
     695             :         // any other error - not specified
     696           0 :         SetError( ERRCODE_IO_GENERAL );
     697           0 :     }
     698           0 : }
     699             : 
     700           0 : UCBStorageStream_Impl::~UCBStorageStream_Impl()
     701             : {
     702           0 :     if( m_rSource.is() )
     703           0 :         m_rSource.clear();
     704             : 
     705           0 :     if( m_pStream )
     706           0 :         delete m_pStream;
     707             : 
     708           0 :     if ( !m_aTempURL.isEmpty() )
     709           0 :         ::utl::UCBContentHelper::Kill( m_aTempURL );
     710             : 
     711           0 :     if( m_pContent )
     712           0 :         delete m_pContent;
     713           0 : }
     714             : 
     715             : 
     716           0 : bool UCBStorageStream_Impl::Init()
     717             : {
     718           0 :     if( m_nRepresentMode == xinputstream )
     719             :     {
     720             :         OSL_FAIL( "XInputStream misuse!" );
     721           0 :         SetError( ERRCODE_IO_ACCESSDENIED );
     722           0 :         return false;
     723             :     }
     724             : 
     725           0 :     if( !m_pStream )
     726             :     {
     727             :         // no temporary stream was created
     728             :         // create one
     729             : 
     730           0 :         m_nRepresentMode = svstream; // can not be used as XInputStream
     731             : 
     732           0 :         if ( m_aTempURL.isEmpty() )
     733           0 :             m_aTempURL = ::utl::TempFile().GetURL();
     734             : 
     735           0 :         m_pStream = ::utl::UcbStreamHelper::CreateStream( m_aTempURL, STREAM_STD_READWRITE, true /* bFileExists */ );
     736             : #if OSL_DEBUG_LEVEL > 1
     737             :         ++nOpenFiles;
     738             : #endif
     739             : 
     740           0 :         if( !m_pStream )
     741             :         {
     742             :             OSL_FAIL( "Suspicious temporary stream creation!" );
     743           0 :             SetError( SVSTREAM_CANNOT_MAKE );
     744           0 :             return false;
     745             :         }
     746             : 
     747           0 :         SetError( m_pStream->GetError() );
     748             :     }
     749             : 
     750           0 :     if( m_bSourceRead && !m_rSource.is() )
     751             :     {
     752             :         // source file contain useful information and is not opened
     753             :         // open it from the point of noncopied data
     754             : 
     755             :         try
     756             :         {
     757           0 :             m_rSource = m_pContent->openStream();
     758             :         }
     759           0 :         catch (const Exception&)
     760             :         {
     761             :             // usually means that stream could not be opened
     762             :         }
     763             : 
     764           0 :         if( m_rSource.is() )
     765             :         {
     766           0 :             m_pStream->Seek( STREAM_SEEK_TO_END );
     767             : 
     768             :             try
     769             :             {
     770           0 :                 m_rSource->skipBytes( m_pStream->Tell() );
     771             :             }
     772           0 :             catch (const BufferSizeExceededException&)
     773             :             {
     774             :                 // the temporary stream already contain all the data
     775           0 :                 m_bSourceRead = false;
     776             :             }
     777           0 :             catch (const Exception&)
     778             :             {
     779             :                 // something is really wrong
     780           0 :                 m_bSourceRead = false;
     781             :                 OSL_FAIL( "Can not operate original stream!" );
     782           0 :                 SetError( SVSTREAM_CANNOT_MAKE );
     783             :             }
     784             : 
     785           0 :             m_pStream->Seek( 0 );
     786             :         }
     787             :         else
     788             :         {
     789             :             // if the new file is edited than no source exist
     790           0 :             m_bSourceRead = false;
     791             :                 //SetError( SVSTREAM_CANNOT_MAKE );
     792             :         }
     793             :     }
     794             : 
     795             :     DBG_ASSERT( m_rSource.is() || !m_bSourceRead, "Unreadable source stream!" );
     796             : 
     797           0 :     return true;
     798             : }
     799             : 
     800           0 : sal_uLong UCBStorageStream_Impl::ReadSourceWriteTemporary()
     801             : {
     802             :     // read source stream till the end and copy all the data to
     803             :     // the current position of the temporary stream
     804             : 
     805           0 :     sal_uLong aResult = 0;
     806             : 
     807           0 :     if( m_bSourceRead )
     808             :     {
     809           0 :         Sequence<sal_Int8> aData(32000);
     810             : 
     811             :         try
     812             :         {
     813             :             sal_uLong aReaded;
     814           0 :             do
     815             :             {
     816           0 :                 aReaded = m_rSource->readBytes( aData, 32000 );
     817           0 :                 aResult += m_pStream->Write( aData.getArray(), aReaded );
     818             :             } while( aReaded == 32000 );
     819             :         }
     820           0 :         catch (const Exception &e)
     821             :         {
     822             :             OSL_FAIL( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
     823             :             (void)e;
     824           0 :         }
     825             :     }
     826             : 
     827           0 :     m_bSourceRead = false;
     828             : 
     829           0 :     return aResult;
     830             : 
     831             : }
     832             : 
     833           0 : sal_uInt64 UCBStorageStream_Impl::ReadSourceWriteTemporary(sal_uInt64 aLength)
     834             : {
     835             :     // read aLength bite from the source stream and copy them to the current
     836             :     // position of the temporary stream
     837             : 
     838           0 :     sal_uInt64 aResult = 0;
     839             : 
     840           0 :     if( m_bSourceRead )
     841             :     {
     842           0 :         Sequence<sal_Int8> aData(32000);
     843             : 
     844             :         try
     845             :         {
     846             : 
     847           0 :             sal_uLong aReaded = 32000;
     848             : 
     849           0 :             for (sal_uInt64 pInd = 0; pInd < aLength && aReaded == 32000 ; pInd += 32000)
     850             :             {
     851           0 :                 sal_uLong aToCopy = min( aLength - pInd, 32000 );
     852           0 :                 aReaded = m_rSource->readBytes( aData, aToCopy );
     853           0 :                 aResult += m_pStream->Write( aData.getArray(), aReaded );
     854             :             }
     855             : 
     856           0 :             if( aResult < aLength )
     857           0 :                 m_bSourceRead = false;
     858             :         }
     859           0 :         catch( const Exception & e )
     860             :         {
     861             :             OSL_FAIL( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
     862             :             (void)e;
     863           0 :         }
     864             :     }
     865             : 
     866           0 :     return aResult;
     867             : }
     868             : 
     869           0 : sal_uLong UCBStorageStream_Impl::CopySourceToTemporary()
     870             : {
     871             :     // current position of the temporary stream is not changed
     872           0 :     sal_uLong aResult = 0;
     873             : 
     874           0 :     if( m_bSourceRead )
     875             :     {
     876           0 :         sal_uLong aPos = m_pStream->Tell();
     877           0 :         m_pStream->Seek( STREAM_SEEK_TO_END );
     878           0 :         aResult = ReadSourceWriteTemporary();
     879           0 :         m_pStream->Seek( aPos );
     880             :     }
     881             : 
     882           0 :     return aResult;
     883             : 
     884             : }
     885             : 
     886             : // UCBStorageStream_Impl must have a SvStream interface, because it then can be used as underlying stream
     887             : // of an OLEStorage; so every write access caused by storage operations marks the UCBStorageStream as modified
     888           0 : sal_uLong UCBStorageStream_Impl::GetData( void* pData, sal_uLong nSize )
     889             : {
     890           0 :     sal_uLong aResult = 0;
     891             : 
     892           0 :     if( !Init() )
     893           0 :         return 0;
     894             : 
     895             : 
     896             :     // read data that is in temporary stream
     897           0 :     aResult = m_pStream->Read( pData, nSize );
     898           0 :     if( m_bSourceRead && aResult < nSize )
     899             :     {
     900             :         // read the tail of the data from original stream
     901             :         // copy this tail to the temporary stream
     902             : 
     903           0 :         sal_uLong aToRead = nSize - aResult;
     904           0 :         pData = static_cast<void*>( static_cast<char*>(pData) + aResult );
     905             : 
     906             :         try
     907             :         {
     908           0 :             Sequence<sal_Int8> aData( aToRead );
     909           0 :             sal_uLong aReaded = m_rSource->readBytes( aData, aToRead );
     910           0 :             aResult += m_pStream->Write( static_cast<void*>(aData.getArray()), aReaded );
     911           0 :             memcpy( pData, aData.getArray(), aReaded );
     912             :         }
     913           0 :         catch (const Exception &e)
     914             :         {
     915             :             OSL_FAIL( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
     916             :             (void)e;
     917             :         }
     918             : 
     919           0 :         if( aResult < nSize )
     920           0 :             m_bSourceRead = false;
     921             :     }
     922             : 
     923           0 :     return aResult;
     924             : }
     925             : 
     926           0 : sal_uLong UCBStorageStream_Impl::PutData( const void* pData, sal_uLong nSize )
     927             : {
     928           0 :     if ( !(m_nMode & StreamMode::WRITE) )
     929             :     {
     930           0 :         SetError( ERRCODE_IO_ACCESSDENIED );
     931           0 :         return 0; // ?mav?
     932             :     }
     933             : 
     934           0 :     if( !nSize || !Init() )
     935           0 :         return 0;
     936             : 
     937           0 :     sal_uLong aResult = m_pStream->Write( pData, nSize );
     938             : 
     939           0 :     m_bModified = aResult > 0;
     940             : 
     941           0 :     return aResult;
     942             : 
     943             : }
     944             : 
     945           0 : sal_uInt64 UCBStorageStream_Impl::SeekPos(sal_uInt64 const nPos)
     946             : {
     947             :     // check if a truncated STREAM_SEEK_TO_END was passed
     948             :     assert(nPos != SAL_MAX_UINT32);
     949             : 
     950           0 :     if( !Init() )
     951           0 :         return 0;
     952             : 
     953             :     sal_uInt64 aResult;
     954             : 
     955           0 :     if( nPos == STREAM_SEEK_TO_END )
     956             :     {
     957           0 :         m_pStream->Seek( STREAM_SEEK_TO_END );
     958           0 :         ReadSourceWriteTemporary();
     959           0 :         aResult = m_pStream->Tell();
     960             :     }
     961             :     else
     962             :     {
     963             :         // the problem is that even if nPos is larger the length
     964             :         // of the stream the stream pointer will be moved to this position
     965             :         // so we have to check if temporary stream does not contain required position
     966             : 
     967           0 :         if( m_pStream->Tell() > nPos
     968           0 :             || m_pStream->Seek( STREAM_SEEK_TO_END ) > nPos )
     969             :         {
     970             :             // no copiing is required
     971           0 :             aResult = m_pStream->Seek( nPos );
     972             :         }
     973             :         else
     974             :         {
     975             :             // the temp stream pointer points to the end now
     976           0 :             aResult = m_pStream->Tell();
     977             : 
     978           0 :             if( aResult < nPos )
     979             :             {
     980           0 :                 if( m_bSourceRead )
     981             :                 {
     982           0 :                     aResult += ReadSourceWriteTemporary( nPos - aResult );
     983           0 :                     if( aResult < nPos )
     984           0 :                         m_bSourceRead = false;
     985             : 
     986             :                     DBG_ASSERT( aResult == m_pStream->Tell(), "Error in stream arithmetic!\n" );
     987             :                 }
     988             : 
     989           0 :                 if( (m_nMode & StreamMode::WRITE) && !m_bSourceRead && aResult < nPos )
     990             :                 {
     991             :                     // it means that all the Source stream was copied already
     992             :                     // but the required position still was not reached
     993             :                     // for writable streams it should be done
     994           0 :                     m_pStream->SetStreamSize( nPos );
     995           0 :                     aResult = m_pStream->Seek( STREAM_SEEK_TO_END );
     996             :                     DBG_ASSERT( aResult == nPos, "Error in stream arithmetic!\n" );
     997             :                 }
     998             :             }
     999             :         }
    1000             :     }
    1001             : 
    1002           0 :     return aResult;
    1003             : }
    1004             : 
    1005           0 : void  UCBStorageStream_Impl::SetSize(sal_uInt64 const nSize)
    1006             : {
    1007           0 :     if ( !(m_nMode & StreamMode::WRITE) )
    1008             :     {
    1009           0 :         SetError( ERRCODE_IO_ACCESSDENIED );
    1010           0 :         return;
    1011             :     }
    1012             : 
    1013           0 :     if( !Init() )
    1014           0 :         return;
    1015             : 
    1016           0 :     m_bModified = true;
    1017             : 
    1018           0 :     if( m_bSourceRead )
    1019             :     {
    1020           0 :         sal_uInt64 const aPos = m_pStream->Tell();
    1021           0 :         m_pStream->Seek( STREAM_SEEK_TO_END );
    1022           0 :         if( m_pStream->Tell() < nSize )
    1023           0 :             ReadSourceWriteTemporary( nSize - m_pStream->Tell() );
    1024           0 :         m_pStream->Seek( aPos );
    1025             :     }
    1026             : 
    1027           0 :     m_pStream->SetStreamSize( nSize );
    1028           0 :     m_bSourceRead = false;
    1029             : }
    1030             : 
    1031           0 : void  UCBStorageStream_Impl::FlushData()
    1032             : {
    1033           0 :     if( m_pStream )
    1034             :     {
    1035           0 :         CopySourceToTemporary();
    1036           0 :         m_pStream->Flush();
    1037             :     }
    1038             : 
    1039           0 :     m_bCommited = true;
    1040           0 : }
    1041             : 
    1042           0 : void UCBStorageStream_Impl::SetError( sal_uInt32 nErr )
    1043             : {
    1044           0 :     if ( !m_nError )
    1045             :     {
    1046           0 :         m_nError = nErr;
    1047           0 :         SvStream::SetError( nErr );
    1048           0 :         if ( m_pAntiImpl ) m_pAntiImpl->SetError( nErr );
    1049             :     }
    1050           0 : }
    1051             : 
    1052           0 : void  UCBStorageStream_Impl::ResetError()
    1053             : {
    1054           0 :     m_nError = 0;
    1055           0 :     SvStream::ResetError();
    1056           0 :     if ( m_pAntiImpl )
    1057           0 :         m_pAntiImpl->ResetError();
    1058           0 : }
    1059             : 
    1060           0 : sal_uLong UCBStorageStream_Impl::GetSize()
    1061             : {
    1062           0 :     if( !Init() )
    1063           0 :         return 0;
    1064             : 
    1065           0 :     sal_uLong nPos = m_pStream->Tell();
    1066           0 :     m_pStream->Seek( STREAM_SEEK_TO_END );
    1067           0 :     ReadSourceWriteTemporary();
    1068           0 :     sal_uLong nRet = m_pStream->Tell();
    1069           0 :     m_pStream->Seek( nPos );
    1070             : 
    1071           0 :     return nRet;
    1072             : }
    1073             : 
    1074           0 : BaseStorage* UCBStorageStream_Impl::CreateStorage()
    1075             : {
    1076             :     // create an OLEStorage on a SvStream ( = this )
    1077             :     // it gets the root attribute because otherwise it would probably not write before my root is committed
    1078           0 :     UCBStorageStream* pNewStorageStream = new UCBStorageStream( this );
    1079           0 :     Storage *pStorage = new Storage( *pNewStorageStream, m_bDirect );
    1080             : 
    1081             :     // GetError() call cleares error code for OLE storages, must be changed in future
    1082           0 :     long nTmpErr = pStorage->GetError();
    1083           0 :     pStorage->SetError( nTmpErr );
    1084             : 
    1085           0 :     m_bIsOLEStorage = !nTmpErr;
    1086           0 :     return static_cast< BaseStorage* > ( pStorage );
    1087             : }
    1088             : 
    1089           0 : sal_Int16 UCBStorageStream_Impl::Commit()
    1090             : {
    1091             :     // send stream to the original content
    1092             :     // the  parent storage is responsible for the correct handling of deleted contents
    1093           0 :     if ( m_bCommited || m_bIsOLEStorage || m_bDirect )
    1094             :     {
    1095             :         // modified streams with OLEStorages on it have autocommit; it is assumed that the OLEStorage
    1096             :         // was committed as well ( if not opened in direct mode )
    1097             : 
    1098           0 :         if ( m_bModified )
    1099             :         {
    1100             :             try
    1101             :             {
    1102           0 :                 CopySourceToTemporary();
    1103             : 
    1104             :                 // release all stream handles
    1105           0 :                 Free();
    1106             : 
    1107             :                 // the temporary file does not exist only for truncated streams
    1108             :                 DBG_ASSERT( !m_aTempURL.isEmpty() || ( m_nMode & StreamMode::TRUNC ), "No temporary file to read from!");
    1109           0 :                 if ( m_aTempURL.isEmpty() && !( m_nMode & StreamMode::TRUNC ) )
    1110           0 :                     throw RuntimeException();
    1111             : 
    1112             :                 // create wrapper to stream that is only used while reading inside package component
    1113           0 :                 Reference < XInputStream > xStream = new FileStreamWrapper_Impl( m_aTempURL );
    1114             : 
    1115           0 :                 Any aAny;
    1116           0 :                 InsertCommandArgument aArg;
    1117           0 :                 aArg.Data = xStream;
    1118           0 :                 aArg.ReplaceExisting = true;
    1119           0 :                 aAny <<= aArg;
    1120           0 :                 m_pContent->executeCommand( OUString("insert"), aAny );
    1121             : 
    1122             :                 // wrapper now controls lifetime of temporary file
    1123           0 :                 m_aTempURL.clear();
    1124             : 
    1125           0 :                 INetURLObject aObj( m_aURL );
    1126           0 :                 aObj.SetName( m_aName );
    1127           0 :                 m_aURL = aObj.GetMainURL( INetURLObject::NO_DECODE );
    1128           0 :                 m_bModified = false;
    1129           0 :                 m_bSourceRead = true;
    1130             :             }
    1131           0 :             catch (const CommandAbortedException&)
    1132             :             {
    1133             :                 // any command wasn't executed successfully - not specified
    1134           0 :                 SetError( ERRCODE_IO_GENERAL );
    1135           0 :                 return COMMIT_RESULT_FAILURE;
    1136             :             }
    1137           0 :             catch (const RuntimeException&)
    1138             :             {
    1139             :                 // any other error - not specified
    1140           0 :                 SetError( ERRCODE_IO_GENERAL );
    1141           0 :                 return COMMIT_RESULT_FAILURE;
    1142             :             }
    1143           0 :             catch (const Exception&)
    1144             :             {
    1145             :                 // any other error - not specified
    1146           0 :                 SetError( ERRCODE_IO_GENERAL );
    1147           0 :                 return COMMIT_RESULT_FAILURE;
    1148             :             }
    1149             : 
    1150           0 :             m_bCommited = false;
    1151           0 :             return COMMIT_RESULT_SUCCESS;
    1152             :         }
    1153             :     }
    1154             : 
    1155           0 :     return COMMIT_RESULT_NOTHING_TO_DO;
    1156             : }
    1157             : 
    1158           0 : bool UCBStorageStream_Impl::Revert()
    1159             : {
    1160             :     // if an OLEStorage is created on this stream, no "revert" is necessary because OLEStorages do nothing on "Revert" !
    1161           0 :     if ( m_bCommited )
    1162             :     {
    1163             :         OSL_FAIL("Revert while commit is in progress!" );
    1164           0 :         return false;                   //  ???
    1165             :     }
    1166             : 
    1167           0 :     Free();
    1168           0 :     if ( !m_aTempURL.isEmpty() )
    1169             :     {
    1170           0 :         ::utl::UCBContentHelper::Kill( m_aTempURL );
    1171           0 :         m_aTempURL.clear();
    1172             :     }
    1173             : 
    1174           0 :     m_bSourceRead = false;
    1175             :     try
    1176             :     {
    1177           0 :         m_rSource = m_pContent->openStream();
    1178           0 :         if( m_rSource.is() )
    1179             :         {
    1180           0 :             if ( m_pAntiImpl && ( m_nMode & StreamMode::TRUNC ) )
    1181             :                 // stream is in use and should be truncated
    1182           0 :                 m_bSourceRead = false;
    1183             :             else
    1184             :             {
    1185           0 :                 m_nMode &= ~StreamMode::TRUNC;
    1186           0 :                 m_bSourceRead = true;
    1187             :             }
    1188             :         }
    1189             :         else
    1190           0 :             SetError( SVSTREAM_CANNOT_MAKE );
    1191             :     }
    1192           0 :     catch (const ContentCreationException&)
    1193             :     {
    1194           0 :         SetError( ERRCODE_IO_GENERAL );
    1195             :     }
    1196           0 :     catch (const RuntimeException&)
    1197             :     {
    1198           0 :         SetError( ERRCODE_IO_GENERAL );
    1199             :     }
    1200           0 :     catch (const Exception&)
    1201             :     {
    1202             :     }
    1203             : 
    1204           0 :     m_bModified = false;
    1205           0 :     m_aName = m_aOriginalName;
    1206           0 :     m_aContentType = m_aOriginalContentType;
    1207           0 :     return ( GetError() == ERRCODE_NONE );
    1208             : }
    1209             : 
    1210           0 : bool UCBStorageStream_Impl::Clear()
    1211             : {
    1212           0 :     bool bRet = ( m_pAntiImpl == NULL );
    1213             :     DBG_ASSERT( bRet, "Removing used stream!" );
    1214           0 :     if( bRet )
    1215             :     {
    1216           0 :         Free();
    1217             :     }
    1218             : 
    1219           0 :     return bRet;
    1220             : }
    1221             : 
    1222           0 : void UCBStorageStream_Impl::Free()
    1223             : {
    1224             : #if OSL_DEBUG_LEVEL > 1
    1225             :     if ( m_pStream )
    1226             :     {
    1227             :         if ( !m_aTempURL.isEmpty() )
    1228             :             --nOpenFiles;
    1229             :         else
    1230             :             --nOpenStreams;
    1231             :     }
    1232             : #endif
    1233             : 
    1234           0 :     m_nRepresentMode = nonset;
    1235           0 :     m_rSource.clear();
    1236           0 :     DELETEZ( m_pStream );
    1237           0 : }
    1238             : 
    1239           0 : void UCBStorageStream_Impl::PrepareCachedForReopen( StreamMode nMode )
    1240             : {
    1241           0 :     bool isWritable = bool( m_nMode & StreamMode::WRITE );
    1242           0 :     if ( isWritable )
    1243             :     {
    1244             :         // once stream was writable, never reset to readonly
    1245           0 :         nMode |= StreamMode::WRITE;
    1246             :     }
    1247             : 
    1248           0 :     m_nMode = nMode;
    1249           0 :     Free();
    1250             : 
    1251           0 :     if ( nMode & StreamMode::TRUNC )
    1252             :     {
    1253           0 :         m_bSourceRead = false; // usually it should be 0 already but just in case...
    1254             : 
    1255           0 :         if ( !m_aTempURL.isEmpty() )
    1256             :         {
    1257           0 :             ::utl::UCBContentHelper::Kill( m_aTempURL );
    1258           0 :             m_aTempURL.clear();
    1259             :         }
    1260             :     }
    1261           0 : }
    1262             : 
    1263           0 : UCBStorageStream::UCBStorageStream( const OUString& rName, StreamMode nMode, bool bDirect, const OString* pKey, bool bRepair, Reference< XProgressHandler > xProgress )
    1264             : {
    1265             :     // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
    1266             :     // to class UCBStorageStream !
    1267           0 :     pImp = new UCBStorageStream_Impl( rName, nMode, this, bDirect, pKey, bRepair, xProgress );
    1268           0 :     pImp->AddFirstRef();             // use direct refcounting because in header file only a pointer should be used
    1269           0 :     StorageBase::m_nMode = pImp->m_nMode;
    1270           0 : }
    1271             : 
    1272           0 : UCBStorageStream::UCBStorageStream( UCBStorageStream_Impl *pImpl )
    1273           0 :     : pImp( pImpl )
    1274             : {
    1275           0 :     pImp->AddFirstRef();             // use direct refcounting because in header file only a pointer should be used
    1276           0 :     pImp->m_pAntiImpl = this;
    1277           0 :     SetError( pImp->m_nError );
    1278           0 :     StorageBase::m_nMode = pImp->m_nMode;
    1279           0 : }
    1280             : 
    1281           0 : UCBStorageStream::~UCBStorageStream()
    1282             : {
    1283           0 :     if ( pImp->m_nMode & StreamMode::WRITE )
    1284           0 :         pImp->Flush();
    1285           0 :     pImp->m_pAntiImpl = NULL;
    1286           0 :     pImp->Free();
    1287           0 :     pImp->ReleaseRef();
    1288           0 : }
    1289             : 
    1290           0 : sal_uLong UCBStorageStream::Read( void * pData, sal_uLong nSize )
    1291             : {
    1292             :     //return pImp->m_pStream->Read( pData, nSize );
    1293           0 :     return pImp->GetData( pData, nSize );
    1294             : }
    1295             : 
    1296           0 : sal_uLong UCBStorageStream::Write( const void* pData, sal_uLong nSize )
    1297             : {
    1298           0 :     return pImp->PutData( pData, nSize );
    1299             : }
    1300             : 
    1301           0 : sal_uInt64 UCBStorageStream::Seek( sal_uInt64 nPos )
    1302             : {
    1303             :     //return pImp->m_pStream->Seek( nPos );
    1304           0 :     return pImp->Seek( nPos );
    1305             : }
    1306             : 
    1307           0 : sal_uLong UCBStorageStream::Tell()
    1308             : {
    1309           0 :     if( !pImp->Init() )
    1310           0 :         return 0;
    1311           0 :     return pImp->m_pStream->Tell();
    1312             : }
    1313             : 
    1314           0 : void UCBStorageStream::Flush()
    1315             : {
    1316             :     // streams are never really transacted, so flush also means commit !
    1317           0 :     Commit();
    1318           0 : }
    1319             : 
    1320           0 : bool UCBStorageStream::SetSize( sal_uLong nNewSize )
    1321             : {
    1322           0 :     pImp->SetSize( nNewSize );
    1323           0 :     return !pImp->GetError();
    1324             : }
    1325             : 
    1326           0 : bool UCBStorageStream::Validate( bool bWrite ) const
    1327             : {
    1328           0 :     return ( !bWrite || ( pImp->m_nMode & StreamMode::WRITE ) );
    1329             : }
    1330             : 
    1331           0 : bool UCBStorageStream::ValidateMode( StreamMode m ) const
    1332             : {
    1333             :     // ???
    1334           0 :     if( m == ( StreamMode::READ | StreamMode::TRUNC ) )  // from stg.cxx
    1335           0 :         return true;
    1336           0 :     if( ( m & STREAM_READWRITE) == StreamMode::READ )
    1337             :     {
    1338             :         // only SHARE_DENYWRITE or SHARE_DENYALL allowed
    1339           0 :         if( ( m & StreamMode::SHARE_DENYWRITE )
    1340           0 :          || ( m & StreamMode::SHARE_DENYALL ) )
    1341           0 :             return true;
    1342             :     }
    1343             :     else
    1344             :     {
    1345             :         // only SHARE_DENYALL allowed
    1346             :         // storages open in r/o mode are OK, since only
    1347             :         // the commit may fail
    1348           0 :         if( m & StreamMode::SHARE_DENYALL )
    1349           0 :             return true;
    1350             :     }
    1351             : 
    1352           0 :     return true;
    1353             : }
    1354             : 
    1355           0 : const SvStream* UCBStorageStream::GetSvStream() const
    1356             : {
    1357           0 :     if( !pImp->Init() )
    1358           0 :         return NULL;
    1359             : 
    1360           0 :     pImp->CopySourceToTemporary();
    1361           0 :     return pImp->m_pStream; // should not live longer then pImp!!!
    1362             : }
    1363             : 
    1364           0 : SvStream* UCBStorageStream::GetModifySvStream()
    1365             : {
    1366           0 :     return static_cast<SvStream*>(pImp);
    1367             : }
    1368             : 
    1369           0 : bool  UCBStorageStream::Equals( const BaseStorageStream& rStream ) const
    1370             : {
    1371             :     // ???
    1372           0 :     return static_cast<BaseStorageStream const *>(this) == &rStream;
    1373             : }
    1374             : 
    1375           0 : bool UCBStorageStream::Commit()
    1376             : {
    1377             :     // mark this stream for sending it on root commit
    1378           0 :     pImp->FlushData();
    1379           0 :     return true;
    1380             : }
    1381             : 
    1382           0 : bool UCBStorageStream::Revert()
    1383             : {
    1384           0 :     return pImp->Revert();
    1385             : }
    1386             : 
    1387           0 : bool UCBStorageStream::CopyTo( BaseStorageStream* pDestStm )
    1388             : {
    1389           0 :     if( !pImp->Init() )
    1390           0 :         return false;
    1391             : 
    1392           0 :     UCBStorageStream* pStg = PTR_CAST( UCBStorageStream, pDestStm );
    1393           0 :     if ( pStg )
    1394           0 :         pStg->pImp->m_aContentType = pImp->m_aContentType;
    1395             : 
    1396           0 :     pDestStm->SetSize( 0 );
    1397           0 :     Seek( STREAM_SEEK_TO_END );
    1398           0 :     sal_Int32 n = Tell();
    1399           0 :     if( n < 0 )
    1400           0 :         return false;
    1401             : 
    1402           0 :     if( pDestStm->SetSize( n ) && n )
    1403             :     {
    1404           0 :         boost::scoped_array<sal_uInt8> p(new sal_uInt8[ 4096 ]);
    1405           0 :         Seek( 0L );
    1406           0 :         pDestStm->Seek( 0L );
    1407           0 :         while( n )
    1408             :         {
    1409           0 :             sal_uInt32 nn = n;
    1410           0 :             if( nn > 4096 )
    1411           0 :                 nn = 4096;
    1412           0 :             if( Read( p.get(), nn ) != nn )
    1413           0 :                 break;
    1414           0 :             if( pDestStm->Write( p.get(), nn ) != nn )
    1415           0 :                 break;
    1416           0 :             n -= nn;
    1417           0 :         }
    1418             :     }
    1419             : 
    1420           0 :     return true;
    1421             : }
    1422             : 
    1423           0 : bool UCBStorageStream::SetProperty( const OUString& rName, const ::com::sun::star::uno::Any& rValue )
    1424             : {
    1425           0 :     if ( rName == "Title")
    1426           0 :         return false;
    1427             : 
    1428           0 :     if ( rName == "MediaType")
    1429             :     {
    1430           0 :         OUString aTmp;
    1431           0 :         rValue >>= aTmp;
    1432           0 :         pImp->m_aContentType = aTmp;
    1433             :     }
    1434             : 
    1435             :     try
    1436             :     {
    1437           0 :         if ( pImp->m_pContent )
    1438             :         {
    1439           0 :             pImp->m_pContent->setPropertyValue( rName, rValue );
    1440           0 :             return true;
    1441             :         }
    1442             :     }
    1443           0 :     catch (const Exception&)
    1444             :     {
    1445             :     }
    1446             : 
    1447           0 :     return false;
    1448             : }
    1449             : 
    1450           0 : sal_uLong UCBStorageStream::GetSize() const
    1451             : {
    1452           0 :     return pImp->GetSize();
    1453             : }
    1454             : 
    1455          30 : UCBStorage::UCBStorage( SvStream& rStrm, bool bDirect )
    1456             : {
    1457          30 :     OUString aURL = GetLinkedFile( rStrm );
    1458          30 :     if ( !aURL.isEmpty() )
    1459             :     {
    1460           0 :         StreamMode nMode = StreamMode::READ;
    1461           0 :         if( rStrm.IsWritable() )
    1462           0 :             nMode = StreamMode::READ | StreamMode::WRITE;
    1463             : 
    1464           0 :         ::ucbhelper::Content aContent( aURL, Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() );
    1465           0 :         pImp = new UCBStorage_Impl( aContent, aURL, nMode, this, bDirect, true );
    1466             :     }
    1467             :     else
    1468             :     {
    1469             :         // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
    1470             :         // to class UCBStorage !
    1471          30 :         pImp = new UCBStorage_Impl( rStrm, this, bDirect );
    1472             :     }
    1473             : 
    1474          30 :     pImp->AddFirstRef();
    1475          30 :     pImp->Init();
    1476          30 :     StorageBase::m_nMode = pImp->m_nMode;
    1477          30 : }
    1478             : 
    1479           0 : UCBStorage::UCBStorage( const ::ucbhelper::Content& rContent, const OUString& rName, StreamMode nMode, bool bDirect, bool bIsRoot )
    1480             : {
    1481             :     // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
    1482             :     // to class UCBStorage !
    1483           0 :     pImp = new UCBStorage_Impl( rContent, rName, nMode, this, bDirect, bIsRoot );
    1484           0 :     pImp->AddFirstRef();
    1485           0 :     pImp->Init();
    1486           0 :     StorageBase::m_nMode = pImp->m_nMode;
    1487           0 : }
    1488             : 
    1489           0 : UCBStorage::UCBStorage( const OUString& rName, StreamMode nMode, bool bDirect, bool bIsRoot, bool bIsRepair, Reference< XProgressHandler > xProgressHandler )
    1490             : {
    1491             :     // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
    1492             :     // to class UCBStorage !
    1493           0 :     pImp = new UCBStorage_Impl( rName, nMode, this, bDirect, bIsRoot, bIsRepair, xProgressHandler );
    1494           0 :     pImp->AddFirstRef();
    1495           0 :     pImp->Init();
    1496           0 :     StorageBase::m_nMode = pImp->m_nMode;
    1497           0 : }
    1498             : 
    1499        2006 : UCBStorage::UCBStorage( const OUString& rName, StreamMode nMode, bool bDirect, bool bIsRoot )
    1500             : {
    1501             :     // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
    1502             :     // to class UCBStorage !
    1503        2006 :     pImp = new UCBStorage_Impl( rName, nMode, this, bDirect, bIsRoot, false, Reference< XProgressHandler >() );
    1504        2006 :     pImp->AddFirstRef();
    1505        2006 :     pImp->Init();
    1506        2006 :     StorageBase::m_nMode = pImp->m_nMode;
    1507        2006 : }
    1508             : 
    1509           0 : UCBStorage::UCBStorage( UCBStorage_Impl *pImpl )
    1510           0 :     : pImp( pImpl )
    1511             : {
    1512           0 :     pImp->m_pAntiImpl = this;
    1513           0 :     SetError( pImp->m_nError );
    1514           0 :     pImp->AddFirstRef();             // use direct refcounting because in header file only a pointer should be used
    1515           0 :     StorageBase::m_nMode = pImp->m_nMode;
    1516           0 : }
    1517             : 
    1518        6108 : UCBStorage::~UCBStorage()
    1519             : {
    1520        2036 :     if ( pImp->m_bIsRoot && pImp->m_bDirect && ( !pImp->m_pTempFile || pImp->m_pSource ) )
    1521             :         // DirectMode is simulated with an AutoCommit
    1522           0 :         Commit();
    1523             : 
    1524        2036 :     pImp->m_pAntiImpl = NULL;
    1525        2036 :     pImp->ReleaseRef();
    1526        4072 : }
    1527             : 
    1528           0 : UCBStorage_Impl::UCBStorage_Impl( const ::ucbhelper::Content& rContent, const OUString& rName, StreamMode nMode, UCBStorage* pStorage, bool bDirect, bool bIsRoot, bool bIsRepair, Reference< XProgressHandler > xProgressHandler  )
    1529             :     : m_pAntiImpl( pStorage )
    1530           0 :     , m_pContent( new ::ucbhelper::Content( rContent ) )
    1531             :     , m_pTempFile( NULL )
    1532             :     , m_pSource( NULL )
    1533             :     //, m_pStream( NULL )
    1534             :     , m_nError( 0 )
    1535             :     , m_nMode( nMode )
    1536             :     , m_bModified( false )
    1537             :     , m_bCommited( false )
    1538             :     , m_bDirect( bDirect )
    1539             :     , m_bIsRoot( bIsRoot )
    1540             :     , m_bDirty( false )
    1541             :     , m_bIsLinked( true )
    1542             :     , m_bListCreated( false )
    1543             :     , m_nFormat( SotClipboardFormatId::NONE )
    1544             :     , m_aClassId( SvGlobalName() )
    1545             :     , m_bRepairPackage( bIsRepair )
    1546           0 :     , m_xProgressHandler( xProgressHandler )
    1547             : {
    1548           0 :     OUString aName( rName );
    1549           0 :     if( aName.isEmpty() )
    1550             :     {
    1551             :         // no name given = use temporary name!
    1552             :         DBG_ASSERT( m_bIsRoot, "SubStorage must have a name!" );
    1553           0 :         m_pTempFile = new ::utl::TempFile;
    1554           0 :         m_pTempFile->EnableKillingFile( true );
    1555           0 :         m_aName = m_aOriginalName = aName = m_pTempFile->GetURL();
    1556             :     }
    1557             : 
    1558           0 :     m_aURL = rName;
    1559           0 : }
    1560             : 
    1561        2006 : UCBStorage_Impl::UCBStorage_Impl( const OUString& rName, StreamMode nMode, UCBStorage* pStorage, bool bDirect, bool bIsRoot, bool bIsRepair, Reference< XProgressHandler > xProgressHandler )
    1562             :     : m_pAntiImpl( pStorage )
    1563             :     , m_pContent( NULL )
    1564             :     , m_pTempFile( NULL )
    1565             :     , m_pSource( NULL )
    1566             :     //, m_pStream( NULL )
    1567             :     , m_nError( 0 )
    1568             :     , m_nMode( nMode )
    1569             :     , m_bModified( false )
    1570             :     , m_bCommited( false )
    1571             :     , m_bDirect( bDirect )
    1572             :     , m_bIsRoot( bIsRoot )
    1573             :     , m_bDirty( false )
    1574             :     , m_bIsLinked( false )
    1575             :     , m_bListCreated( false )
    1576             :     , m_nFormat( SotClipboardFormatId::NONE )
    1577             :     , m_aClassId( SvGlobalName() )
    1578             :     , m_bRepairPackage( bIsRepair )
    1579        2006 :     , m_xProgressHandler( xProgressHandler )
    1580             : {
    1581        2006 :     OUString aName( rName );
    1582        2006 :     if( aName.isEmpty() )
    1583             :     {
    1584             :         // no name given = use temporary name!
    1585             :         DBG_ASSERT( m_bIsRoot, "SubStorage must have a name!" );
    1586        2006 :         m_pTempFile = new ::utl::TempFile;
    1587        2006 :         m_pTempFile->EnableKillingFile( true );
    1588        2006 :         m_aName = m_aOriginalName = aName = m_pTempFile->GetURL();
    1589             :     }
    1590             : 
    1591        2006 :     if ( m_bIsRoot )
    1592             :     {
    1593             :         // create the special package URL for the package content
    1594        2006 :         OUString aTemp = "vnd.sun.star.pkg://";
    1595        2006 :         aTemp += INetURLObject::encode( aName, INetURLObject::PART_AUTHORITY, INetURLObject::ENCODE_ALL );
    1596        2006 :         m_aURL = aTemp;
    1597             : 
    1598        2006 :         if ( m_nMode & StreamMode::WRITE )
    1599             :         {
    1600             :             // the root storage opens the package, so make sure that there is any
    1601        2006 :             SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aName, STREAM_STD_READWRITE, m_pTempFile != 0 /* bFileExists */ );
    1602        2006 :             delete pStream;
    1603        2006 :         }
    1604             :     }
    1605             :     else
    1606             :     {
    1607             :         // substorages are opened like streams: the URL is a "child URL" of the root package URL
    1608           0 :         m_aURL = rName;
    1609           0 :         if ( !m_aURL.startsWith( "vnd.sun.star.pkg://") )
    1610           0 :             m_bIsLinked = true;
    1611        2006 :     }
    1612        2006 : }
    1613             : 
    1614          30 : UCBStorage_Impl::UCBStorage_Impl( SvStream& rStream, UCBStorage* pStorage, bool bDirect )
    1615             :     : m_pAntiImpl( pStorage )
    1616             :     , m_pContent( NULL )
    1617          30 :     , m_pTempFile( new ::utl::TempFile )
    1618             :     , m_pSource( &rStream )
    1619             :     , m_nError( 0 )
    1620             :     , m_bModified( false )
    1621             :     , m_bCommited( false )
    1622             :     , m_bDirect( bDirect )
    1623             :     , m_bIsRoot( true )
    1624             :     , m_bDirty( false )
    1625             :     , m_bIsLinked( false )
    1626             :     , m_bListCreated( false )
    1627             :     , m_nFormat( SotClipboardFormatId::NONE )
    1628             :     , m_aClassId( SvGlobalName() )
    1629          60 :     , m_bRepairPackage( false )
    1630             : {
    1631             :     // opening in direct mode is too fuzzy because the data is transferred to the stream in the Commit() call,
    1632             :     // which will be called in the storages' dtor
    1633          30 :     m_pTempFile->EnableKillingFile( true );
    1634             :     DBG_ASSERT( !bDirect, "Storage on a stream must not be opened in direct mode!" );
    1635             : 
    1636             :     // UCBStorages work on a content, so a temporary file for a content must be created, even if the stream is only
    1637             :     // accessed readonly
    1638             :     // the root storage opens the package; create the special package URL for the package content
    1639          30 :     OUString aTemp = "vnd.sun.star.pkg://";
    1640          30 :     aTemp += INetURLObject::encode( m_pTempFile->GetURL(), INetURLObject::PART_AUTHORITY, INetURLObject::ENCODE_ALL );
    1641          30 :     m_aURL = aTemp;
    1642             : 
    1643             :     // copy data into the temporary file
    1644          60 :     boost::scoped_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( m_pTempFile->GetURL(), STREAM_STD_READWRITE, true /* bFileExists */ ));
    1645          30 :     if ( pStream )
    1646             :     {
    1647          30 :         rStream.Seek(0);
    1648          30 :         rStream.ReadStream( *pStream );
    1649          30 :         pStream->Flush();
    1650          30 :         pStream.reset();
    1651             :     }
    1652             : 
    1653             :     // close stream and let content access the file
    1654          30 :     m_pSource->Seek(0);
    1655             : 
    1656             :     // check opening mode
    1657          30 :     m_nMode = StreamMode::READ;
    1658          30 :     if( rStream.IsWritable() )
    1659          60 :         m_nMode = StreamMode::READ | StreamMode::WRITE;
    1660          30 : }
    1661             : 
    1662        2036 : void UCBStorage_Impl::Init()
    1663             : {
    1664             :     // name is last segment in URL
    1665        2036 :     INetURLObject aObj( m_aURL );
    1666        2036 :     if ( m_aName.isEmpty() )
    1667             :         // if the name was not already set to a temp name
    1668          30 :         m_aName = m_aOriginalName = aObj.GetLastName();
    1669             : 
    1670        2036 :     if ( !m_pContent )
    1671        2036 :         CreateContent();
    1672             : 
    1673        2036 :     if ( m_pContent )
    1674             :     {
    1675          13 :         if ( m_bIsLinked )
    1676             :         {
    1677           0 :             if( m_bIsRoot )
    1678             :             {
    1679           0 :                 ReadContent();
    1680           0 :                 if ( m_nError == ERRCODE_NONE )
    1681             :                 {
    1682             :                     // read the manifest.xml file
    1683           0 :                     aObj.Append( OUString( "META-INF" ) );
    1684           0 :                     aObj.Append( OUString( "manifest.xml" ) );
    1685             : 
    1686             :                     // create input stream
    1687           0 :                     boost::scoped_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( aObj.GetMainURL( INetURLObject::NO_DECODE ), STREAM_STD_READ ));
    1688             :                     // no stream means no manifest.xml
    1689           0 :                     if ( pStream )
    1690             :                     {
    1691           0 :                         if ( !pStream->GetError() )
    1692             :                         {
    1693           0 :                             ::utl::OInputStreamWrapper* pHelper = new ::utl::OInputStreamWrapper( *pStream );
    1694           0 :                             com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > xInputStream( pHelper );
    1695             : 
    1696             :                             // create a manifest reader object that will read in the manifest from the stream
    1697             :                             Reference < ::com::sun::star::packages::manifest::XManifestReader > xReader =
    1698             :                                 ::com::sun::star::packages::manifest::ManifestReader::create(
    1699           0 :                                     ::comphelper::getProcessComponentContext() ) ;
    1700           0 :                             Sequence < Sequence < PropertyValue > > aProps = xReader->readManifestSequence( xInputStream );
    1701             : 
    1702             :                             // cleanup
    1703           0 :                             xReader = NULL;
    1704           0 :                             xInputStream = NULL;
    1705           0 :                             SetProps( aProps, OUString() );
    1706             :                         }
    1707           0 :                     }
    1708             :                 }
    1709             :             }
    1710             :             else
    1711           0 :                 ReadContent();
    1712             :         }
    1713             :         else
    1714             :         {
    1715             :             // get the manifest information from the package
    1716             :             try {
    1717          13 :                 Any aAny = m_pContent->getPropertyValue("MediaType");
    1718          26 :                 OUString aTmp;
    1719          13 :                 if ( ( aAny >>= aTmp ) && !aTmp.isEmpty() )
    1720          13 :                     m_aContentType = m_aOriginalContentType = aTmp;
    1721             :             }
    1722           0 :             catch (const Exception&)
    1723             :             {
    1724             :                 DBG_ASSERT( false,
    1725             :                             "getPropertyValue has thrown an exception! Please let developers know the scenario!" );
    1726             :             }
    1727             :         }
    1728             :     }
    1729             : 
    1730        2036 :     if ( !m_aContentType.isEmpty() )
    1731             :     {
    1732             :         // get the clipboard format using the content type
    1733           0 :         ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
    1734           0 :         aDataFlavor.MimeType = m_aContentType;
    1735           0 :         m_nFormat = SotExchange::GetFormat( aDataFlavor );
    1736             : 
    1737             :         // get the ClassId using the clipboard format ( internal table )
    1738           0 :         m_aClassId = GetClassId_Impl( m_nFormat );
    1739             : 
    1740             :         // get human presentable name using the clipboard format
    1741           0 :         SotExchange::GetFormatDataFlavor( m_nFormat, aDataFlavor );
    1742           0 :         m_aUserTypeName = aDataFlavor.HumanPresentableName;
    1743             : 
    1744           0 :         if( m_pContent && !m_bIsLinked && m_aClassId != SvGlobalName() )
    1745           0 :             ReadContent();
    1746        2036 :     }
    1747        2036 : }
    1748             : 
    1749        4029 : void UCBStorage_Impl::CreateContent()
    1750             : {
    1751             :     try
    1752             :     {
    1753             :         // create content; where to put StreamMode ?! ( already done when opening the file of the package ? )
    1754        4029 :         Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
    1755             : 
    1756        8058 :         OUString aTemp( m_aURL );
    1757             : 
    1758        4029 :         if ( m_bRepairPackage )
    1759             :         {
    1760           0 :             xComEnv = new ::ucbhelper::CommandEnvironment( Reference< ::com::sun::star::task::XInteractionHandler >(),
    1761           0 :                                                      m_xProgressHandler );
    1762           0 :             aTemp += "?repairpackage";
    1763             :         }
    1764             : 
    1765       12074 :         m_pContent = new ::ucbhelper::Content( aTemp, xComEnv, comphelper::getProcessComponentContext() );
    1766             :     }
    1767        8032 :     catch (const ContentCreationException&)
    1768             :     {
    1769             :         // content could not be created
    1770        4016 :         SetError( SVSTREAM_CANNOT_MAKE );
    1771             :     }
    1772           0 :     catch (const RuntimeException&)
    1773             :     {
    1774             :         // any other error - not specified
    1775           0 :         SetError( SVSTREAM_CANNOT_MAKE );
    1776             :     }
    1777        4029 : }
    1778             : 
    1779        4012 : void UCBStorage_Impl::ReadContent()
    1780             : {
    1781        4012 :    if ( m_bListCreated )
    1782        6005 :         return;
    1783             : 
    1784        2006 :     m_bListCreated = true;
    1785             : 
    1786             :     // create cursor for access to children
    1787        2006 :     Sequence< OUString > aProps(4);
    1788        2006 :     aProps[0] = "Title";
    1789        2006 :     aProps[1] = "IsFolder";
    1790        2006 :     aProps[2] = "MediaType";
    1791        2006 :     aProps[3] = "Size";
    1792        2006 :     ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS;
    1793             : 
    1794             :     try
    1795             :     {
    1796        2006 :         GetContent();
    1797        2006 :         if ( !m_pContent )
    1798        1993 :             return;
    1799             : 
    1800          13 :         Reference< XResultSet > xResultSet = m_pContent->createCursor( aProps, eInclude );
    1801          26 :         Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
    1802          26 :         Reference< XRow > xRow( xResultSet, UNO_QUERY );
    1803          13 :         if ( xResultSet.is() )
    1804             :         {
    1805          26 :             while ( xResultSet->next() )
    1806             :             {
    1807             :                 // insert all into the children list
    1808           0 :                 OUString aTitle( xRow->getString(1) );
    1809           0 :                 OUString aContentType;
    1810           0 :                 if ( m_bIsLinked )
    1811             :                 {
    1812             :                     // unpacked storages have to deal with the meta-inf folder by themselves
    1813           0 :                     if ( aTitle == "META-INF" )
    1814           0 :                         continue;
    1815             :                 }
    1816             :                 else
    1817             :                 {
    1818           0 :                     aContentType = xRow->getString(3);
    1819             :                 }
    1820             : 
    1821           0 :                 bool bIsFolder( xRow->getBoolean(2) );
    1822           0 :                 sal_Int64 nSize = xRow->getLong(4);
    1823           0 :                 UCBStorageElement_Impl* pElement = new UCBStorageElement_Impl( aTitle, bIsFolder, (sal_uLong) nSize );
    1824           0 :                 m_aChildrenList.push_back( pElement );
    1825             : 
    1826           0 :                 bool bIsOfficeDocument = m_bIsLinked || ( m_aClassId != SvGlobalName() );
    1827           0 :                 if ( bIsFolder )
    1828             :                 {
    1829           0 :                     if ( m_bIsLinked )
    1830           0 :                         OpenStorage( pElement, m_nMode, m_bDirect );
    1831           0 :                     if ( pElement->m_xStorage.Is() )
    1832           0 :                         pElement->m_xStorage->Init();
    1833             :                 }
    1834           0 :                 else if ( bIsOfficeDocument )
    1835             :                 {
    1836             :                     // streams can be external OLE objects, so they are now folders, but storages!
    1837           0 :                     OUString aName( m_aURL + "/" + xRow->getString(1));
    1838             : 
    1839           0 :                     Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
    1840           0 :                     if ( m_bRepairPackage )
    1841             :                     {
    1842           0 :                         xComEnv = new ::ucbhelper::CommandEnvironment( Reference< ::com::sun::star::task::XInteractionHandler >(),
    1843           0 :                                                                 m_xProgressHandler );
    1844           0 :                         aName += "?repairpackage";
    1845             :                     }
    1846             : 
    1847           0 :                     ::ucbhelper::Content aContent( aName, xComEnv, comphelper::getProcessComponentContext() );
    1848             : 
    1849           0 :                     OUString aMediaType;
    1850           0 :                     Any aAny = aContent.getPropertyValue("MediaType");
    1851           0 :                     if ( ( aAny >>= aMediaType ) && ( aMediaType == "application/vnd.sun.star.oleobject" ) )
    1852           0 :                         pElement->m_bIsStorage = true;
    1853           0 :                     else if ( aMediaType.isEmpty() )
    1854             :                     {
    1855             :                         // older files didn't have that special content type, so they must be detected
    1856           0 :                         OpenStream( pElement, STREAM_STD_READ, m_bDirect );
    1857           0 :                         if ( Storage::IsStorageFile( pElement->m_xStream ) )
    1858           0 :                             pElement->m_bIsStorage = true;
    1859             :                         else
    1860           0 :                             pElement->m_xStream->Free();
    1861           0 :                     }
    1862             :                 }
    1863           0 :             }
    1864          13 :         }
    1865             :     }
    1866           0 :     catch (const InteractiveIOException& r)
    1867             :     {
    1868           0 :         if ( r.Code != IOErrorCode_NOT_EXISTING )
    1869           0 :             SetError( ERRCODE_IO_GENERAL );
    1870             :     }
    1871           0 :     catch (const CommandAbortedException&)
    1872             :     {
    1873             :         // any command wasn't executed successfully - not specified
    1874           0 :         if ( !( m_nMode & StreamMode::WRITE ) )
    1875             :             // if the folder was just inserted and not already committed, this is not an error!
    1876           0 :             SetError( ERRCODE_IO_GENERAL );
    1877             :     }
    1878           0 :     catch (const RuntimeException&)
    1879             :     {
    1880             :         // any other error - not specified
    1881           0 :         SetError( ERRCODE_IO_GENERAL );
    1882             :     }
    1883           0 :     catch (const ResultSetException&)
    1884             :     {
    1885             :         // means that the package file is broken
    1886           0 :         SetError( ERRCODE_IO_BROKENPACKAGE );
    1887             :     }
    1888           0 :     catch (const SQLException&)
    1889             :     {
    1890             :         // means that the file can be broken
    1891           0 :         SetError( ERRCODE_IO_WRONGFORMAT );
    1892             :     }
    1893           0 :     catch (const Exception&)
    1894             :     {
    1895             :         // any other error - not specified
    1896           0 :         SetError( ERRCODE_IO_GENERAL );
    1897          13 :     }
    1898             : }
    1899             : 
    1900        4016 : void UCBStorage_Impl::SetError( long nError )
    1901             : {
    1902        4016 :     if ( !m_nError )
    1903             :     {
    1904        2023 :         m_nError = nError;
    1905        2023 :         if ( m_pAntiImpl ) m_pAntiImpl->SetError( nError );
    1906             :     }
    1907        4016 : }
    1908             : 
    1909           0 : sal_Int32 UCBStorage_Impl::GetObjectCount()
    1910             : {
    1911           0 :     sal_Int32 nCount = m_aChildrenList.size();
    1912           0 :     for ( size_t i = 0; i < m_aChildrenList.size(); ++i )
    1913             :     {
    1914           0 :         UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
    1915             :         DBG_ASSERT( !pElement->m_bIsFolder || pElement->m_xStorage.Is(), "Storage should be open!" );
    1916           0 :         if ( pElement->m_bIsFolder && pElement->m_xStorage.Is() )
    1917           0 :             nCount += pElement->m_xStorage->GetObjectCount();
    1918             :     }
    1919             : 
    1920           0 :     return nCount;
    1921             : }
    1922             : 
    1923           0 : OUString Find_Impl( const Sequence < Sequence < PropertyValue > >& rSequence, const OUString& rPath )
    1924             : {
    1925           0 :     bool bFound = false;
    1926           0 :     for ( sal_Int32 nSeqs=0; nSeqs<rSequence.getLength(); nSeqs++ )
    1927             :     {
    1928           0 :         const Sequence < PropertyValue >& rMyProps = rSequence[nSeqs];
    1929           0 :         OUString aType;
    1930             : 
    1931           0 :         for ( sal_Int32 nProps=0; nProps<rMyProps.getLength(); nProps++ )
    1932             :         {
    1933           0 :             const PropertyValue& rAny = rMyProps[nProps];
    1934           0 :             if ( rAny.Name == "FullPath" )
    1935             :             {
    1936           0 :                 OUString aTmp;
    1937           0 :                 if ( ( rAny.Value >>= aTmp ) && aTmp == rPath )
    1938           0 :                     bFound = true;
    1939           0 :                 if ( !aType.isEmpty() )
    1940           0 :                     break;
    1941             :             }
    1942           0 :             else if ( rAny.Name == "MediaType" )
    1943             :             {
    1944           0 :                 if ( ( rAny.Value >>= aType ) && !aType.isEmpty() && bFound )
    1945           0 :                     break;
    1946             :             }
    1947             :         }
    1948             : 
    1949           0 :         if ( bFound )
    1950           0 :             return aType;
    1951           0 :     }
    1952             : 
    1953           0 :     return OUString();
    1954             : }
    1955             : 
    1956           0 : void UCBStorage_Impl::SetProps( const Sequence < Sequence < PropertyValue > >& rSequence, const OUString& rPath )
    1957             : {
    1958           0 :     OUString aPath( rPath );
    1959           0 :     if ( !m_bIsRoot )
    1960           0 :         aPath += m_aName;
    1961           0 :     aPath += "/";
    1962             : 
    1963           0 :     m_aContentType = m_aOriginalContentType = Find_Impl( rSequence, aPath );
    1964             : 
    1965           0 :     if ( m_bIsRoot )
    1966             :         // the "FullPath" of a child always starts without '/'
    1967           0 :         aPath.clear();
    1968             : 
    1969           0 :     for ( size_t i = 0; i < m_aChildrenList.size(); ++i )
    1970             :     {
    1971           0 :         UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
    1972             :         DBG_ASSERT( !pElement->m_bIsFolder || pElement->m_xStorage.Is(), "Storage should be open!" );
    1973           0 :         if ( pElement->m_bIsFolder && pElement->m_xStorage.Is() )
    1974           0 :             pElement->m_xStorage->SetProps( rSequence, aPath );
    1975             :         else
    1976             :         {
    1977           0 :             OUString aElementPath( aPath );
    1978           0 :             aElementPath += pElement->m_aName;
    1979           0 :             pElement->SetContentType( Find_Impl( rSequence, aElementPath ) );
    1980             :         }
    1981             :     }
    1982             : 
    1983           0 :     if ( !m_aContentType.isEmpty() )
    1984             :     {
    1985             :         // get the clipboard format using the content type
    1986           0 :         ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
    1987           0 :         aDataFlavor.MimeType = m_aContentType;
    1988           0 :         m_nFormat = SotExchange::GetFormat( aDataFlavor );
    1989             : 
    1990             :         // get the ClassId using the clipboard format ( internal table )
    1991           0 :         m_aClassId = GetClassId_Impl( m_nFormat );
    1992             : 
    1993             :         // get human presentable name using the clipboard format
    1994           0 :         SotExchange::GetFormatDataFlavor( m_nFormat, aDataFlavor );
    1995           0 :         m_aUserTypeName = aDataFlavor.HumanPresentableName;
    1996           0 :     }
    1997           0 : }
    1998             : 
    1999           0 : void UCBStorage_Impl::GetProps( sal_Int32& nProps, Sequence < Sequence < PropertyValue > >& rSequence, const OUString& rPath )
    2000             : {
    2001             :     // first my own properties
    2002           0 :     Sequence < PropertyValue > aProps(2);
    2003             : 
    2004             :     // first property is the "FullPath" name
    2005             :     // it's '/' for the root storage and m_aName for each element, followed by a '/' if it's a folder
    2006           0 :     OUString aPath( rPath );
    2007           0 :     if ( !m_bIsRoot )
    2008           0 :         aPath += m_aName;
    2009           0 :     aPath += "/";
    2010           0 :     aProps[0].Name = "MediaType";
    2011           0 :     aProps[0].Value <<= m_aContentType;
    2012           0 :     aProps[1].Name = "FullPath";
    2013           0 :     aProps[1].Value <<= aPath;
    2014           0 :     rSequence[ nProps++ ] = aProps;
    2015             : 
    2016           0 :     if ( m_bIsRoot )
    2017             :         // the "FullPath" of a child always starts without '/'
    2018           0 :         aPath.clear();
    2019             : 
    2020             :     // now the properties of my elements
    2021           0 :     for ( size_t i = 0; i < m_aChildrenList.size(); ++i )
    2022             :     {
    2023           0 :         UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
    2024             :         DBG_ASSERT( !pElement->m_bIsFolder || pElement->m_xStorage.Is(), "Storage should be open!" );
    2025           0 :         if ( pElement->m_bIsFolder && pElement->m_xStorage.Is() )
    2026             :             // storages add there properties by themselves ( see above )
    2027           0 :             pElement->m_xStorage->GetProps( nProps, rSequence, aPath );
    2028             :         else
    2029             :         {
    2030             :             // properties of streams
    2031           0 :             OUString aElementPath( aPath );
    2032           0 :             aElementPath += pElement->m_aName;
    2033           0 :             aProps[0].Name = "MediaType";
    2034           0 :             aProps[0].Value <<= pElement->GetContentType();
    2035           0 :             aProps[1].Name = "FullPath";
    2036           0 :             aProps[1].Value <<= aElementPath;
    2037           0 :             rSequence[ nProps++ ] = aProps;
    2038             :         }
    2039           0 :     }
    2040           0 : }
    2041             : 
    2042        6108 : UCBStorage_Impl::~UCBStorage_Impl()
    2043             : {
    2044             :     // first delete elements!
    2045        2036 :     for ( size_t i = 0, n = m_aChildrenList.size(); i < n; ++i )
    2046           0 :         delete m_aChildrenList[ i ];
    2047        2036 :     m_aChildrenList.clear();
    2048             : 
    2049        2036 :     delete m_pContent;
    2050        2036 :     delete m_pTempFile;
    2051        4072 : }
    2052             : 
    2053           0 : bool UCBStorage_Impl::Insert( ::ucbhelper::Content *pContent )
    2054             : {
    2055             :     // a new substorage is inserted into a UCBStorage ( given by the parameter pContent )
    2056             :     // it must be inserted with a title and a type
    2057           0 :     bool bRet = false;
    2058             : 
    2059             :     try
    2060             :     {
    2061           0 :         Sequence< ContentInfo > aInfo = pContent->queryCreatableContentsInfo();
    2062           0 :         sal_Int32 nCount = aInfo.getLength();
    2063           0 :         if ( nCount == 0 )
    2064           0 :             return false;
    2065             : 
    2066           0 :         for ( sal_Int32 i = 0; i < nCount; ++i )
    2067             :         {
    2068             :             // Simply look for the first KIND_FOLDER...
    2069           0 :             const ContentInfo & rCurr = aInfo[i];
    2070           0 :             if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER )
    2071             :             {
    2072             :                 // Make sure the only required bootstrap property is "Title",
    2073           0 :                 const Sequence< Property > & rProps = rCurr.Properties;
    2074           0 :                 if ( rProps.getLength() != 1 )
    2075           0 :                     continue;
    2076             : 
    2077           0 :                 if ( rProps[ 0 ].Name != "Title" )
    2078           0 :                     continue;
    2079             : 
    2080           0 :                 Sequence < OUString > aNames(1);
    2081           0 :                 aNames[0] = "Title";
    2082           0 :                 Sequence < Any > aValues(1);
    2083           0 :                 aValues[0] = makeAny( OUString( m_aName ) );
    2084             : 
    2085           0 :                 Content aNewFolder;
    2086           0 :                 if ( !pContent->insertNewContent( rCurr.Type, aNames, aValues, aNewFolder ) )
    2087           0 :                     continue;
    2088             : 
    2089             :                 // remove old content, create an "empty" new one and initialize it with the new inserted
    2090           0 :                 DELETEZ( m_pContent );
    2091           0 :                 m_pContent = new ::ucbhelper::Content( aNewFolder );
    2092           0 :                 bRet = true;
    2093             :             }
    2094           0 :         }
    2095             :     }
    2096           0 :     catch (const CommandAbortedException&)
    2097             :     {
    2098             :         // any command wasn't executed successfully - not specified
    2099           0 :         SetError( ERRCODE_IO_GENERAL );
    2100             :     }
    2101           0 :     catch (const RuntimeException&)
    2102             :     {
    2103             :         // any other error - not specified
    2104           0 :         SetError( ERRCODE_IO_GENERAL );
    2105             :     }
    2106           0 :     catch (const Exception&)
    2107             :     {
    2108             :         // any other error - not specified
    2109           0 :         SetError( ERRCODE_IO_GENERAL );
    2110             :     }
    2111             : 
    2112           0 :     return bRet;
    2113             : }
    2114             : 
    2115           0 : sal_Int16 UCBStorage_Impl::Commit()
    2116             : {
    2117             :     // send all changes to the package
    2118           0 :     sal_Int16 nRet = COMMIT_RESULT_NOTHING_TO_DO;
    2119             : 
    2120             :     // there is nothing to do if the storage has been opened readonly or if it was opened in transacted mode and no
    2121             :     // commit command has been sent
    2122           0 :     if ( ( m_nMode & StreamMode::WRITE ) && ( m_bCommited || m_bDirect ) )
    2123             :     {
    2124             :         try
    2125             :         {
    2126             :             // all errors will be caught in the "catch" statement outside the loop
    2127           0 :             for ( size_t i = 0; i < m_aChildrenList.size() && nRet; ++i )
    2128             :             {
    2129           0 :                 UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
    2130           0 :                 ::ucbhelper::Content* pContent = pElement->GetContent();
    2131           0 :                 boost::scoped_ptr< ::ucbhelper::Content > xDeleteContent;
    2132           0 :                 if ( !pContent && pElement->IsModified() )
    2133             :                 {
    2134             :                     // if the element has never been opened, no content has been created until now
    2135           0 :                     OUString aName( m_aURL );
    2136           0 :                     aName += "/";
    2137           0 :                     aName += pElement->m_aOriginalName;
    2138           0 :                     pContent = new ::ucbhelper::Content( aName, Reference< ::com::sun::star::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
    2139           0 :                     xDeleteContent.reset(pContent);  // delete it later on exit scope
    2140             :                 }
    2141             : 
    2142           0 :                 if ( pElement->m_bIsRemoved )
    2143             :                 {
    2144             :                     // was it inserted, then removed (so there would be nothing to do!)
    2145           0 :                     if ( !pElement->m_bIsInserted )
    2146             :                     {
    2147             :                         // first remove all open stream handles
    2148           0 :                         if (pContent && (!pElement->m_xStream.Is() || pElement->m_xStream->Clear()))
    2149             :                         {
    2150           0 :                             pContent->executeCommand( OUString("delete"), makeAny( true ) );
    2151           0 :                             nRet = COMMIT_RESULT_SUCCESS;
    2152             :                         }
    2153             :                         else
    2154             :                             // couldn't release stream because there are external references to it
    2155           0 :                             nRet = COMMIT_RESULT_FAILURE;
    2156             :                     }
    2157             :                 }
    2158             :                 else
    2159             :                 {
    2160           0 :                     sal_Int16 nLocalRet = COMMIT_RESULT_NOTHING_TO_DO;
    2161           0 :                     if ( pElement->m_xStorage.Is() )
    2162             :                     {
    2163             :                         // element is a storage
    2164             :                         // do a commit in the following cases:
    2165             :                         //  - if storage is already inserted, and changed
    2166             :                         //  - storage is not in a package
    2167             :                         //  - it's a new storage, try to insert and commit if successful inserted
    2168           0 :                         if ( !pElement->m_bIsInserted || m_bIsLinked || pElement->m_xStorage->Insert( m_pContent ) )
    2169             :                         {
    2170           0 :                             nLocalRet = pElement->m_xStorage->Commit();
    2171           0 :                             pContent = pElement->GetContent();
    2172             :                         }
    2173             :                     }
    2174           0 :                     else if ( pElement->m_xStream.Is() )
    2175             :                     {
    2176             :                         // element is a stream
    2177           0 :                         nLocalRet = pElement->m_xStream->Commit();
    2178           0 :                         if ( pElement->m_xStream->m_bIsOLEStorage )
    2179             :                         {
    2180             :                             // OLE storage should be stored encrytped, if the storage uses encryption
    2181           0 :                             pElement->m_xStream->m_aContentType = "application/vnd.sun.star.oleobject";
    2182           0 :                             Any aValue;
    2183           0 :                             aValue <<= true;
    2184           0 :                             pElement->m_xStream->m_pContent->setPropertyValue("Encrypted", aValue );
    2185             :                         }
    2186             : 
    2187           0 :                         pContent = pElement->GetContent();
    2188             :                     }
    2189             : 
    2190           0 :                     if (pContent && pElement->m_aName != pElement->m_aOriginalName)
    2191             :                     {
    2192             :                         // name ( title ) of the element was changed
    2193           0 :                         nLocalRet = COMMIT_RESULT_SUCCESS;
    2194           0 :                         Any aAny;
    2195           0 :                         aAny <<= pElement->m_aName;
    2196           0 :                         pContent->setPropertyValue("Title", aAny );
    2197             :                     }
    2198             : 
    2199           0 :                     if (pContent && pElement->IsLoaded() && pElement->GetContentType() != pElement->GetOriginalContentType())
    2200             :                     {
    2201             :                         // mediatype of the element was changed
    2202           0 :                         nLocalRet = COMMIT_RESULT_SUCCESS;
    2203           0 :                         Any aAny;
    2204           0 :                         aAny <<= pElement->GetContentType();
    2205           0 :                         pContent->setPropertyValue("MediaType", aAny );
    2206             :                     }
    2207             : 
    2208           0 :                     if ( nLocalRet != COMMIT_RESULT_NOTHING_TO_DO )
    2209           0 :                         nRet = nLocalRet;
    2210             :                 }
    2211             : 
    2212           0 :                 if ( nRet == COMMIT_RESULT_FAILURE )
    2213           0 :                     break;
    2214           0 :             }
    2215             :         }
    2216           0 :         catch (const ContentCreationException&)
    2217             :         {
    2218             :             // content could not be created
    2219           0 :             SetError( ERRCODE_IO_NOTEXISTS );
    2220           0 :             return COMMIT_RESULT_FAILURE;
    2221             :         }
    2222           0 :         catch (const CommandAbortedException&)
    2223             :         {
    2224             :             // any command wasn't executed successfully - not specified
    2225           0 :             SetError( ERRCODE_IO_GENERAL );
    2226           0 :             return COMMIT_RESULT_FAILURE;
    2227             :         }
    2228           0 :         catch (const RuntimeException&)
    2229             :         {
    2230             :             // any other error - not specified
    2231           0 :             SetError( ERRCODE_IO_GENERAL );
    2232           0 :             return COMMIT_RESULT_FAILURE;
    2233             :         }
    2234           0 :         catch (const Exception&)
    2235             :         {
    2236             :             // any other error - not specified
    2237           0 :             SetError( ERRCODE_IO_GENERAL );
    2238           0 :             return COMMIT_RESULT_FAILURE;
    2239             :         }
    2240             : 
    2241           0 :         if ( m_bIsRoot && m_pContent )
    2242             :         {
    2243             :             // the root storage must flush the root package content
    2244           0 :             if ( nRet == COMMIT_RESULT_SUCCESS )
    2245             :             {
    2246             :                 try
    2247             :                 {
    2248             :                     // commit the media type to the JAR file
    2249             :                     // clipboard format and ClassId will be retrieved from the media type when the file is loaded again
    2250           0 :                     Any aType;
    2251           0 :                     aType <<= m_aContentType;
    2252           0 :                     m_pContent->setPropertyValue("MediaType", aType );
    2253             : 
    2254           0 :                     if (  m_bIsLinked )
    2255             :                     {
    2256             :                         // write a manifest file
    2257             :                         // first create a subfolder "META-inf"
    2258           0 :                         Content aNewSubFolder;
    2259           0 :                         bool bRet = ::utl::UCBContentHelper::MakeFolder( *m_pContent, OUString("META-INF"), aNewSubFolder );
    2260           0 :                         if ( bRet )
    2261             :                         {
    2262             :                             // create a stream to write the manifest file - use a temp file
    2263           0 :                             OUString aURL( aNewSubFolder.getURL() );
    2264           0 :                             boost::scoped_ptr< ::utl::TempFile> pTempFile(new ::utl::TempFile( &aURL ));
    2265             : 
    2266             :                             // get the stream from the temp file and create an output stream wrapper
    2267           0 :                             SvStream* pStream = pTempFile->GetStream( STREAM_STD_READWRITE );
    2268           0 :                             ::utl::OOutputStreamWrapper* pHelper = new ::utl::OOutputStreamWrapper( *pStream );
    2269           0 :                             com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > xOutputStream( pHelper );
    2270             : 
    2271             :                             // create a manifest writer object that will fill the stream
    2272             :                             Reference < ::com::sun::star::packages::manifest::XManifestWriter > xWriter =
    2273             :                                 ::com::sun::star::packages::manifest::ManifestWriter::create(
    2274           0 :                                     ::comphelper::getProcessComponentContext() );
    2275           0 :                             sal_Int32 nCount = GetObjectCount() + 1;
    2276           0 :                             Sequence < Sequence < PropertyValue > > aProps( nCount );
    2277           0 :                             sal_Int32 nProps = 0;
    2278           0 :                             GetProps( nProps, aProps, OUString() );
    2279           0 :                             xWriter->writeManifestSequence( xOutputStream, aProps );
    2280             : 
    2281             :                             // move the stream to its desired location
    2282           0 :                             Content aSource( pTempFile->GetURL(), Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() );
    2283           0 :                             xWriter = NULL;
    2284           0 :                             xOutputStream = NULL;
    2285           0 :                             pTempFile.reset();
    2286           0 :                             aNewSubFolder.transferContent( aSource, InsertOperation_MOVE, OUString("manifest.xml"), NameClash::OVERWRITE );
    2287           0 :                         }
    2288             :                     }
    2289             :                     else
    2290             :                     {
    2291             : #if OSL_DEBUG_LEVEL > 1
    2292             :                         fprintf ( stderr, "Files: %i\n", nOpenFiles );
    2293             :                         fprintf ( stderr, "Streams: %i\n", nOpenStreams );
    2294             : #endif
    2295             :                         // force writing
    2296           0 :                         Any aAny;
    2297           0 :                         m_pContent->executeCommand( OUString("flush"), aAny );
    2298           0 :                         if ( m_pSource != 0 )
    2299             :                         {
    2300           0 :                             boost::scoped_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( m_pTempFile->GetURL(), STREAM_STD_READ ));
    2301           0 :                             m_pSource->SetStreamSize(0);
    2302             :                             // m_pSource->Seek(0);
    2303           0 :                             pStream->ReadStream( *m_pSource );
    2304           0 :                             pStream.reset();
    2305           0 :                             m_pSource->Seek(0);
    2306           0 :                         }
    2307           0 :                     }
    2308             :                 }
    2309           0 :                 catch (const CommandAbortedException&)
    2310             :                 {
    2311             :                     // how to tell the content : forget all changes ?!
    2312             :                     // or should we assume that the content does it by itself because he throwed an exception ?!
    2313             :                     // any command wasn't executed successfully - not specified
    2314           0 :                     SetError( ERRCODE_IO_GENERAL );
    2315           0 :                     return COMMIT_RESULT_FAILURE;
    2316             :                 }
    2317           0 :                 catch (const RuntimeException&)
    2318             :                 {
    2319             :                     // how to tell the content : forget all changes ?!
    2320             :                     // or should we assume that the content does it by itself because he throwed an exception ?!
    2321             :                     // any other error - not specified
    2322           0 :                     SetError( ERRCODE_IO_GENERAL );
    2323           0 :                     return COMMIT_RESULT_FAILURE;
    2324             :                 }
    2325           0 :                 catch (const InteractiveIOException& r)
    2326             :                 {
    2327           0 :                     if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION )
    2328           0 :                         SetError( ERRCODE_IO_ACCESSDENIED );
    2329           0 :                     else if ( r.Code == IOErrorCode_NOT_EXISTING )
    2330           0 :                         SetError( ERRCODE_IO_NOTEXISTS );
    2331           0 :                     else if ( r.Code == IOErrorCode_CANT_READ )
    2332           0 :                         SetError( ERRCODE_IO_CANTREAD );
    2333           0 :                     else if ( r.Code == IOErrorCode_CANT_WRITE )
    2334           0 :                         SetError( ERRCODE_IO_CANTWRITE );
    2335             :                     else
    2336           0 :                         SetError( ERRCODE_IO_GENERAL );
    2337             : 
    2338           0 :                     return COMMIT_RESULT_FAILURE;
    2339             :                 }
    2340           0 :                 catch (const Exception&)
    2341             :                 {
    2342             :                     // how to tell the content : forget all changes ?!
    2343             :                     // or should we assume that the content does it by itself because he throwed an exception ?!
    2344             :                     // any other error - not specified
    2345           0 :                     SetError( ERRCODE_IO_GENERAL );
    2346           0 :                     return COMMIT_RESULT_FAILURE;
    2347             :                 }
    2348             :             }
    2349           0 :             else if ( nRet != COMMIT_RESULT_NOTHING_TO_DO )
    2350             :             {
    2351             :                 // how to tell the content : forget all changes ?! Should we ?!
    2352           0 :                 SetError( ERRCODE_IO_GENERAL );
    2353           0 :                 return nRet;
    2354             :             }
    2355             : 
    2356             :             // after successful root commit all elements names and types are adjusted and all removed elements
    2357             :             // are also removed from the lists
    2358           0 :             for ( size_t i = 0; i < m_aChildrenList.size(); )
    2359             :             {
    2360           0 :                 UCBStorageElement_Impl* pInnerElement = m_aChildrenList[ i ];
    2361           0 :                 if ( pInnerElement->m_bIsRemoved )
    2362             :                 {
    2363           0 :                     UCBStorageElementList_Impl::iterator it = m_aChildrenList.begin();
    2364           0 :                     ::std::advance( it, i );
    2365           0 :                     delete *it;
    2366           0 :                     m_aChildrenList.erase( it );
    2367             :                 }
    2368             :                 else
    2369             :                 {
    2370           0 :                     pInnerElement->m_aOriginalName = pInnerElement->m_aName;
    2371           0 :                     pInnerElement->m_bIsInserted = false;
    2372           0 :                     ++i;
    2373             :                 }
    2374             :             }
    2375             :         }
    2376             : 
    2377           0 :         m_bCommited = false;
    2378             :     }
    2379             : 
    2380           0 :     return nRet;
    2381             : }
    2382             : 
    2383           0 : bool UCBStorage_Impl::Revert()
    2384             : {
    2385           0 :     for ( size_t i = 0; i < m_aChildrenList.size(); )
    2386             :     {
    2387           0 :         UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
    2388           0 :         pElement->m_bIsRemoved = false;
    2389           0 :         if ( pElement->m_bIsInserted )
    2390             :         {
    2391           0 :             UCBStorageElementList_Impl::iterator it = m_aChildrenList.begin();
    2392           0 :             ::std::advance( it, i );
    2393           0 :             delete *it;
    2394           0 :             m_aChildrenList.erase( it );
    2395             :         }
    2396             :         else
    2397             :         {
    2398           0 :             if ( pElement->m_xStream.Is() )
    2399             :             {
    2400           0 :                 pElement->m_xStream->m_bCommited = false;
    2401           0 :                 pElement->m_xStream->Revert();
    2402             :             }
    2403           0 :             else if ( pElement->m_xStorage.Is() )
    2404             :             {
    2405           0 :                 pElement->m_xStorage->m_bCommited = false;
    2406           0 :                 pElement->m_xStorage->Revert();
    2407             :             }
    2408             : 
    2409           0 :             pElement->m_aName = pElement->m_aOriginalName;
    2410           0 :             pElement->m_bIsRemoved = false;
    2411           0 :             ++i;
    2412             :         }
    2413             :     }
    2414           0 :     return true;
    2415             : }
    2416             : 
    2417        2006 : const OUString& UCBStorage::GetName() const
    2418             : {
    2419        2006 :     return pImp->m_aName; // pImp->m_aURL ?!
    2420             : }
    2421             : 
    2422        2036 : bool UCBStorage::IsRoot() const
    2423             : {
    2424        2036 :     return pImp->m_bIsRoot;
    2425             : }
    2426             : 
    2427           0 : void UCBStorage::SetDirty()
    2428             : {
    2429           0 :     pImp->m_bDirty = true;
    2430           0 : }
    2431             : 
    2432           0 : void UCBStorage::SetClass( const SvGlobalName & rClass, SotClipboardFormatId nOriginalClipFormat, const OUString & rUserTypeName )
    2433             : {
    2434           0 :     pImp->m_aClassId = rClass;
    2435           0 :     pImp->m_nFormat = nOriginalClipFormat;
    2436           0 :     pImp->m_aUserTypeName = rUserTypeName;
    2437             : 
    2438             :     // in UCB storages only the content type will be stored, all other information can be reconstructed
    2439             :     // ( see the UCBStorage_Impl::Init() method )
    2440           0 :     ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
    2441           0 :     SotExchange::GetFormatDataFlavor( pImp->m_nFormat, aDataFlavor );
    2442           0 :     pImp->m_aContentType = aDataFlavor.MimeType;
    2443           0 : }
    2444             : 
    2445           0 : void UCBStorage::SetClassId( const ClsId& rClsId )
    2446             : {
    2447           0 :     pImp->m_aClassId = SvGlobalName( rClsId );
    2448           0 :     if ( pImp->m_aClassId == SvGlobalName() )
    2449           0 :         return;
    2450             : 
    2451             :     // in OLE storages the clipboard format an the user name will be transferred when a storage is copied because both are
    2452             :     // stored in one the substreams
    2453             :     // UCB storages store the content type information as content type in the manifest file and so this information must be
    2454             :     // kept up to date, and also the other type information that is hold only at runtime because it can be reconstructed from
    2455             :     // the content type
    2456           0 :     pImp->m_nFormat = GetFormatId_Impl( pImp->m_aClassId );
    2457           0 :     if ( pImp->m_nFormat != SotClipboardFormatId::NONE )
    2458             :     {
    2459           0 :         ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
    2460           0 :         SotExchange::GetFormatDataFlavor( pImp->m_nFormat, aDataFlavor );
    2461           0 :         pImp->m_aUserTypeName = aDataFlavor.HumanPresentableName;
    2462           0 :         pImp->m_aContentType = aDataFlavor.MimeType;
    2463             :     }
    2464             : }
    2465             : 
    2466           0 : const ClsId& UCBStorage::GetClassId() const
    2467             : {
    2468           0 :     return ( const ClsId& ) pImp->m_aClassId.GetCLSID();
    2469             : }
    2470             : 
    2471           0 : void UCBStorage::SetConvertClass( const SvGlobalName & /*rConvertClass*/, SotClipboardFormatId /*nOriginalClipFormat*/, const OUString & /*rUserTypeName*/ )
    2472             : {
    2473             :     // ???
    2474           0 : }
    2475             : 
    2476           0 : bool UCBStorage::ShouldConvert()
    2477             : {
    2478             :     // ???
    2479           0 :     return false;
    2480             : }
    2481             : 
    2482           0 : SvGlobalName UCBStorage::GetClassName()
    2483             : {
    2484           0 :     return  pImp->m_aClassId;
    2485             : }
    2486             : 
    2487           0 : SotClipboardFormatId UCBStorage::GetFormat()
    2488             : {
    2489           0 :     return pImp->m_nFormat;
    2490             : }
    2491             : 
    2492           0 : OUString UCBStorage::GetUserName()
    2493             : {
    2494             :     OSL_FAIL("UserName is not implemented in UCB storages!" );
    2495           0 :     return pImp->m_aUserTypeName;
    2496             : }
    2497             : 
    2498           0 : void UCBStorage::FillInfoList( SvStorageInfoList* pList ) const
    2499             : {
    2500             :     // put information in childrenlist into StorageInfoList
    2501           0 :     for ( size_t i = 0; i < pImp->GetChildrenList().size(); ++i )
    2502             :     {
    2503           0 :         UCBStorageElement_Impl* pElement = pImp->GetChildrenList()[ i ];
    2504           0 :         if ( !pElement->m_bIsRemoved )
    2505             :         {
    2506             :             // problem: what about the size of a substorage ?!
    2507           0 :             sal_uLong nSize = pElement->m_nSize;
    2508           0 :             if ( pElement->m_xStream.Is() )
    2509           0 :                 nSize = pElement->m_xStream->GetSize();
    2510           0 :             SvStorageInfo aInfo( pElement->m_aName, nSize, pElement->m_bIsStorage );
    2511           0 :             pList->push_back( aInfo );
    2512             :         }
    2513             :     }
    2514           0 : }
    2515             : 
    2516           0 : bool UCBStorage::CopyStorageElement_Impl( UCBStorageElement_Impl& rElement, BaseStorage* pDest, const OUString& rNew ) const
    2517             : {
    2518             :     // insert stream or storage into the list or stream of the destination storage
    2519             :     // not into the content, this will be done on commit !
    2520             :     // be aware of name changes !
    2521           0 :     if ( !rElement.m_bIsStorage )
    2522             :     {
    2523             :         // copy the streams data
    2524             :         // the destination stream must not be open
    2525           0 :         boost::scoped_ptr<BaseStorageStream> pOtherStream(pDest->OpenStream( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pImp->m_bDirect ));
    2526           0 :         BaseStorageStream* pStream = NULL;
    2527           0 :         bool bDeleteStream = false;
    2528             : 
    2529             :         // if stream is already open, it is allowed to copy it, so be aware of this
    2530           0 :         if ( rElement.m_xStream.Is() )
    2531           0 :             pStream = rElement.m_xStream->m_pAntiImpl;
    2532           0 :         if ( !pStream )
    2533             :         {
    2534           0 :             pStream = ( const_cast < UCBStorage* > (this) )->OpenStream( rElement.m_aName, STREAM_STD_READ, pImp->m_bDirect );
    2535           0 :             bDeleteStream = true;
    2536             :         }
    2537             : 
    2538           0 :         pStream->CopyTo( pOtherStream.get() );
    2539           0 :         SetError( pStream->GetError() );
    2540           0 :         if( pOtherStream->GetError() )
    2541           0 :             pDest->SetError( pOtherStream->GetError() );
    2542             :         else
    2543           0 :             pOtherStream->Commit();
    2544             : 
    2545           0 :         if ( bDeleteStream )
    2546           0 :             delete pStream;
    2547             :     }
    2548             :     else
    2549             :     {
    2550             :         // copy the storage content
    2551             :         // the destination storage must not be open
    2552           0 :         BaseStorage* pStorage = NULL;
    2553             : 
    2554             :         // if stream is already open, it is allowed to copy it, so be aware of this
    2555           0 :         bool bDeleteStorage = false;
    2556           0 :         if ( rElement.m_xStorage.Is() )
    2557           0 :             pStorage = rElement.m_xStorage->m_pAntiImpl;
    2558           0 :         if ( !pStorage )
    2559             :         {
    2560           0 :             pStorage = ( const_cast < UCBStorage* > (this) )->OpenStorage( rElement.m_aName, pImp->m_nMode, pImp->m_bDirect );
    2561           0 :             bDeleteStorage = true;
    2562             :         }
    2563             : 
    2564           0 :         UCBStorage* pUCBDest = PTR_CAST( UCBStorage, pDest );
    2565           0 :         UCBStorage* pUCBCopy = PTR_CAST( UCBStorage, pStorage );
    2566             : 
    2567           0 :         bool bOpenUCBStorage = pUCBDest && pUCBCopy;
    2568             :         boost::scoped_ptr<BaseStorage> pOtherStorage(bOpenUCBStorage ?
    2569           0 :                 pDest->OpenUCBStorage( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pImp->m_bDirect ) :
    2570           0 :                 pDest->OpenOLEStorage( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pImp->m_bDirect ));
    2571             : 
    2572             :         // For UCB storages, the class id and the format id may differ,
    2573             :         // do passing the class id is not sufficient.
    2574           0 :         if( bOpenUCBStorage )
    2575           0 :             pOtherStorage->SetClass( pStorage->GetClassName(),
    2576           0 :                                      pStorage->GetFormat(),
    2577           0 :                                      pUCBCopy->pImp->m_aUserTypeName );
    2578             :         else
    2579           0 :             pOtherStorage->SetClassId( pStorage->GetClassId() );
    2580           0 :         pStorage->CopyTo( pOtherStorage.get() );
    2581           0 :         SetError( pStorage->GetError() );
    2582           0 :         if( pOtherStorage->GetError() )
    2583           0 :             pDest->SetError( pOtherStorage->GetError() );
    2584             :         else
    2585           0 :             pOtherStorage->Commit();
    2586             : 
    2587           0 :         if ( bDeleteStorage )
    2588           0 :             delete pStorage;
    2589             :     }
    2590             : 
    2591           0 :     return Good() && pDest->Good();
    2592             : }
    2593             : 
    2594        4012 : UCBStorageElement_Impl* UCBStorage::FindElement_Impl( const OUString& rName ) const
    2595             : {
    2596             :     DBG_ASSERT( !rName.isEmpty(), "Name is empty!" );
    2597        4012 :     for ( size_t i = 0, n = pImp->GetChildrenList().size(); i < n; ++i )
    2598             :     {
    2599           0 :         UCBStorageElement_Impl* pElement = pImp->GetChildrenList()[ i ];
    2600           0 :         if ( pElement->m_aName == rName && !pElement->m_bIsRemoved )
    2601           0 :             return pElement;
    2602             :     }
    2603        4012 :     return NULL;
    2604             : }
    2605             : 
    2606           0 : bool UCBStorage::CopyTo( BaseStorage* pDestStg ) const
    2607             : {
    2608             :     DBG_ASSERT( pDestStg != static_cast<BaseStorage const *>(this), "Self-Copying is not possible!" );
    2609           0 :     if ( pDestStg == static_cast<BaseStorage const *>(this) )
    2610           0 :         return false;
    2611             : 
    2612             :     // perhaps it's also a problem if one storage is a parent of the other ?!
    2613             :     // or if not: could be optimized ?!
    2614             : 
    2615             :     // For UCB storages, the class id and the format id may differ,
    2616             :     // do passing the class id is not sufficient.
    2617           0 :     if( pDestStg->ISA( UCBStorage ) )
    2618             :         pDestStg->SetClass( pImp->m_aClassId, pImp->m_nFormat,
    2619           0 :                             pImp->m_aUserTypeName );
    2620             :     else
    2621           0 :         pDestStg->SetClassId( GetClassId() );
    2622           0 :     pDestStg->SetDirty();
    2623             : 
    2624           0 :     bool bRet = true;
    2625           0 :     for ( size_t i = 0; i < pImp->GetChildrenList().size() && bRet; ++i )
    2626             :     {
    2627           0 :         UCBStorageElement_Impl* pElement = pImp->GetChildrenList()[ i ];
    2628           0 :         if ( !pElement->m_bIsRemoved )
    2629           0 :             bRet = CopyStorageElement_Impl( *pElement, pDestStg, pElement->m_aName );
    2630             :     }
    2631             : 
    2632           0 :     if( !bRet )
    2633           0 :         SetError( pDestStg->GetError() );
    2634           0 :     return Good() && pDestStg->Good();
    2635             : }
    2636             : 
    2637           0 : bool UCBStorage::CopyTo( const OUString& rElemName, BaseStorage* pDest, const OUString& rNew )
    2638             : {
    2639           0 :     if( rElemName.isEmpty() )
    2640           0 :         return false;
    2641             : 
    2642           0 :     if ( pDest == static_cast<BaseStorage*>(this) )
    2643             :     {
    2644             :         // can't double an element
    2645           0 :         return false;
    2646             :     }
    2647             :     else
    2648             :     {
    2649             :         // for copying no optimization is useful, because in every case the stream data must be copied
    2650           0 :             UCBStorageElement_Impl* pElement = FindElement_Impl( rElemName );
    2651           0 :         if ( pElement )
    2652           0 :             return CopyStorageElement_Impl( *pElement, pDest, rNew );
    2653             :         else
    2654             :         {
    2655           0 :             SetError( SVSTREAM_FILE_NOT_FOUND );
    2656           0 :             return false;
    2657             :         }
    2658             :     }
    2659             : }
    2660             : 
    2661           0 : bool UCBStorage::Commit()
    2662             : {
    2663             :     // mark this storage for sending it on root commit
    2664           0 :     pImp->m_bCommited = true;
    2665           0 :     if ( pImp->m_bIsRoot )
    2666             :         // the root storage coordinates committing by sending a Commit command to its content
    2667           0 :         return ( pImp->Commit() != COMMIT_RESULT_FAILURE );
    2668             :     else
    2669           0 :         return true;
    2670             : }
    2671             : 
    2672           0 : bool UCBStorage::Revert()
    2673             : {
    2674           0 :     return pImp->Revert();
    2675             : }
    2676             : 
    2677           0 : BaseStorageStream* UCBStorage::OpenStream( const OUString& rEleName, StreamMode nMode, bool bDirect, const OString* pKey )
    2678             : {
    2679           0 :     if( rEleName.isEmpty() )
    2680           0 :         return NULL;
    2681             : 
    2682             :     // try to find the storage element
    2683           0 :     UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
    2684           0 :     if ( !pElement )
    2685             :     {
    2686             :         // element does not exist, check if creation is allowed
    2687           0 :         if( ( nMode & StreamMode::NOCREATE ) )
    2688             :         {
    2689           0 :             SetError( ( nMode & StreamMode::WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
    2690           0 :             OUString aName( pImp->m_aURL );
    2691           0 :             aName += "/";
    2692           0 :             aName += rEleName;
    2693           0 :             UCBStorageStream* pStream = new UCBStorageStream( aName, nMode, bDirect, pKey, pImp->m_bRepairPackage, pImp->m_xProgressHandler );
    2694           0 :             pStream->SetError( GetError() );
    2695           0 :             pStream->pImp->m_aName = rEleName;
    2696           0 :             return pStream;
    2697             :         }
    2698             :         else
    2699             :         {
    2700             :             // create a new UCBStorageElement and insert it into the list
    2701           0 :             pElement = new UCBStorageElement_Impl( rEleName );
    2702           0 :             pElement->m_bIsInserted = true;
    2703           0 :             pImp->m_aChildrenList.push_back( pElement );
    2704             :         }
    2705             :     }
    2706             : 
    2707           0 :     if ( !pElement->m_bIsFolder )
    2708             :     {
    2709             :         // check if stream is already created
    2710           0 :         if ( pElement->m_xStream.Is() )
    2711             :         {
    2712             :             // stream has already been created; if it has no external reference, it may be opened another time
    2713           0 :             if ( pElement->m_xStream->m_pAntiImpl )
    2714             :             {
    2715             :                 OSL_FAIL("Stream is already open!" );
    2716           0 :                 SetError( SVSTREAM_ACCESS_DENIED );  // ???
    2717           0 :                 return NULL;
    2718             :             }
    2719             :             else
    2720             :             {
    2721             :                 // check if stream is opened with the same keyword as before
    2722             :                 // if not, generate a new stream because it could be encrypted vs. decrypted!
    2723           0 :                 OString aKey;
    2724           0 :                 if ( pKey )
    2725           0 :                     aKey = *pKey;
    2726           0 :                 if ( pElement->m_xStream->m_aKey == aKey )
    2727             :                 {
    2728           0 :                     pElement->m_xStream->PrepareCachedForReopen( nMode );
    2729             : 
    2730           0 :                     return new UCBStorageStream( pElement->m_xStream );
    2731           0 :                 }
    2732             :             }
    2733             :         }
    2734             : 
    2735             :         // stream is opened the first time
    2736           0 :         pImp->OpenStream( pElement, nMode, bDirect, pKey );
    2737             : 
    2738             :         // if name has been changed before creating the stream: set name!
    2739           0 :         pElement->m_xStream->m_aName = rEleName;
    2740           0 :         return new UCBStorageStream( pElement->m_xStream );
    2741             :     }
    2742             : 
    2743           0 :     return NULL;
    2744             : }
    2745             : 
    2746           0 : UCBStorageStream_Impl* UCBStorage_Impl::OpenStream( UCBStorageElement_Impl* pElement, StreamMode nMode, bool bDirect, const OString* pKey )
    2747             : {
    2748           0 :     OUString aName( m_aURL );
    2749           0 :     aName += "/";
    2750           0 :     aName += pElement->m_aOriginalName;
    2751           0 :     pElement->m_xStream = new UCBStorageStream_Impl( aName, nMode, NULL, bDirect, pKey, m_bRepairPackage, m_xProgressHandler );
    2752           0 :     return pElement->m_xStream;
    2753             : }
    2754             : 
    2755           0 : BaseStorage* UCBStorage::OpenUCBStorage( const OUString& rEleName, StreamMode nMode, bool bDirect )
    2756             : {
    2757           0 :     if( rEleName.isEmpty() )
    2758           0 :         return NULL;
    2759             : 
    2760           0 :     return OpenStorage_Impl( rEleName, nMode, bDirect, true );
    2761             : }
    2762             : 
    2763           0 : BaseStorage* UCBStorage::OpenOLEStorage( const OUString& rEleName, StreamMode nMode, bool bDirect )
    2764             : {
    2765           0 :     if( rEleName.isEmpty() )
    2766           0 :         return NULL;
    2767             : 
    2768           0 :     return OpenStorage_Impl( rEleName, nMode, bDirect, false );
    2769             : }
    2770             : 
    2771           0 : BaseStorage* UCBStorage::OpenStorage( const OUString& rEleName, StreamMode nMode, bool bDirect )
    2772             : {
    2773           0 :     if( rEleName.isEmpty() )
    2774           0 :         return NULL;
    2775             : 
    2776           0 :     return OpenStorage_Impl( rEleName, nMode, bDirect, true );
    2777             : }
    2778             : 
    2779           0 : BaseStorage* UCBStorage::OpenStorage_Impl( const OUString& rEleName, StreamMode nMode, bool bDirect, bool bForceUCBStorage )
    2780             : {
    2781             :     // try to find the storage element
    2782           0 :     UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
    2783           0 :     if ( !pElement )
    2784             :     {
    2785             :         // element does not exist, check if creation is allowed
    2786           0 :         if( ( nMode & StreamMode::NOCREATE ) )
    2787             :         {
    2788           0 :             SetError( ( nMode & StreamMode::WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
    2789           0 :             OUString aName( pImp->m_aURL );
    2790           0 :             aName += "/";
    2791           0 :             aName += rEleName;  //  ???
    2792           0 :             UCBStorage *pStorage = new UCBStorage( aName, nMode, bDirect, false, pImp->m_bRepairPackage, pImp->m_xProgressHandler );
    2793           0 :             pStorage->pImp->m_bIsRoot = false;
    2794           0 :             pStorage->pImp->m_bListCreated = true; // the storage is pretty new, nothing to read
    2795           0 :             pStorage->SetError( GetError() );
    2796           0 :             return pStorage;
    2797             :         }
    2798             : 
    2799             :         // create a new UCBStorageElement and insert it into the list
    2800             :         // problem: perhaps an OLEStorage should be created ?!
    2801             :         // Because nothing is known about the element that should be created, an external parameter is needed !
    2802           0 :         pElement = new UCBStorageElement_Impl( rEleName );
    2803           0 :         pElement->m_bIsInserted = true;
    2804           0 :         pImp->m_aChildrenList.push_back( pElement );
    2805             :     }
    2806             : 
    2807           0 :     if ( !pElement->m_bIsFolder && ( pElement->m_bIsStorage || !bForceUCBStorage ) )
    2808             :     {
    2809             :         // create OLE storages on a stream ( see ctor of SotStorage )
    2810             :         // Such a storage will be created on a UCBStorageStream; it will write into the stream
    2811             :         // if it is opened in direct mode or when it is committed. In this case the stream will be
    2812             :         // modified and then it MUST be treated as committed.
    2813           0 :         if ( !pElement->m_xStream.Is() )
    2814             :         {
    2815           0 :             BaseStorageStream* pStr = OpenStream( rEleName, nMode, bDirect );
    2816           0 :             UCBStorageStream* pStream = PTR_CAST( UCBStorageStream, pStr );
    2817           0 :             if ( !pStream )
    2818             :             {
    2819           0 :                 SetError( ( nMode & StreamMode::WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
    2820           0 :                 return NULL;
    2821             :             }
    2822             : 
    2823           0 :             pElement->m_xStream = pStream->pImp;
    2824           0 :             delete pStream;
    2825             :         }
    2826             : 
    2827           0 :         pElement->m_xStream->PrepareCachedForReopen( nMode );
    2828           0 :         bool bInited = pElement->m_xStream->Init();
    2829           0 :         if (!bInited)
    2830             :         {
    2831           0 :             SetError( ( nMode & StreamMode::WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
    2832           0 :             return NULL;
    2833             :         }
    2834             : 
    2835           0 :         pElement->m_bIsStorage = true;
    2836           0 :         return pElement->m_xStream->CreateStorage();  // can only be created in transacted mode
    2837             :     }
    2838           0 :     else if ( pElement->m_xStorage.Is() )
    2839             :     {
    2840             :         // storage has already been opened; if it has no external reference, it may be opened another time
    2841           0 :         if ( pElement->m_xStorage->m_pAntiImpl )
    2842             :         {
    2843             :             OSL_FAIL("Storage is already open!" );
    2844           0 :             SetError( SVSTREAM_ACCESS_DENIED );  // ???
    2845             :         }
    2846             :         else
    2847             :         {
    2848           0 :             bool bIsWritable = bool( pElement->m_xStorage->m_nMode & StreamMode::WRITE );
    2849           0 :             if ( !bIsWritable && ( nMode & StreamMode::WRITE ) )
    2850             :             {
    2851           0 :                 OUString aName( pImp->m_aURL );
    2852           0 :                 aName += "/";
    2853           0 :                 aName += pElement->m_aOriginalName;
    2854           0 :                 UCBStorage* pStorage = new UCBStorage( aName, nMode, bDirect, false, pImp->m_bRepairPackage, pImp->m_xProgressHandler );
    2855           0 :                 pElement->m_xStorage = pStorage->pImp;
    2856           0 :                 return pStorage;
    2857             :             }
    2858             :             else
    2859             :             {
    2860           0 :                 return new UCBStorage( pElement->m_xStorage );
    2861             :             }
    2862             :         }
    2863             :     }
    2864           0 :     else if ( !pElement->m_xStream.Is() )
    2865             :     {
    2866             :         // storage is opened the first time
    2867           0 :         bool bIsWritable = bool(pImp->m_nMode & StreamMode::WRITE);
    2868           0 :         if ( pImp->m_bIsLinked && pImp->m_bIsRoot && bIsWritable )
    2869             :         {
    2870             :             // make sure that the root storage object has been created before substorages will be created
    2871           0 :             INetURLObject aFolderObj( pImp->m_aURL );
    2872           0 :             aFolderObj.removeSegment();
    2873             : 
    2874           0 :             Content aFolder( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ), Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() );
    2875           0 :             pImp->m_pContent = new Content;
    2876           0 :             bool bRet = ::utl::UCBContentHelper::MakeFolder( aFolder, pImp->m_aName, *pImp->m_pContent );
    2877           0 :             if ( !bRet )
    2878             :             {
    2879           0 :                 SetError( SVSTREAM_CANNOT_MAKE );
    2880           0 :                 return NULL;
    2881           0 :             }
    2882             :         }
    2883             : 
    2884           0 :         UCBStorage_Impl* pStor = pImp->OpenStorage( pElement, nMode, bDirect );
    2885           0 :         if ( pStor )
    2886             :         {
    2887           0 :             if ( pElement->m_bIsInserted )
    2888           0 :                 pStor->m_bListCreated = true; // the storage is pretty new, nothing to read
    2889             : 
    2890           0 :             return new UCBStorage( pStor );
    2891             :         }
    2892             :     }
    2893             : 
    2894           0 :     return NULL;
    2895             : }
    2896             : 
    2897           0 : UCBStorage_Impl* UCBStorage_Impl::OpenStorage( UCBStorageElement_Impl* pElement, StreamMode nMode, bool bDirect )
    2898             : {
    2899           0 :     UCBStorage_Impl* pRet = NULL;
    2900           0 :     OUString aName( m_aURL );
    2901           0 :     aName += "/";
    2902           0 :     aName += pElement->m_aOriginalName;  //  ???
    2903             : 
    2904           0 :     pElement->m_bIsStorage = pElement->m_bIsFolder = true;
    2905             : 
    2906           0 :     if ( m_bIsLinked && !::utl::UCBContentHelper::Exists( aName ) )
    2907             :     {
    2908           0 :         Content aNewFolder;
    2909           0 :         bool bRet = ::utl::UCBContentHelper::MakeFolder( *m_pContent, pElement->m_aOriginalName, aNewFolder );
    2910           0 :         if ( bRet )
    2911           0 :             pRet = new UCBStorage_Impl( aNewFolder, aName, nMode, NULL, bDirect, false, m_bRepairPackage, m_xProgressHandler );
    2912             :     }
    2913             :     else
    2914             :     {
    2915           0 :         pRet = new UCBStorage_Impl( aName, nMode, NULL, bDirect, false, m_bRepairPackage, m_xProgressHandler );
    2916             :     }
    2917             : 
    2918           0 :     if ( pRet )
    2919             :     {
    2920           0 :         pRet->m_bIsLinked = m_bIsLinked;
    2921           0 :         pRet->m_bIsRoot = false;
    2922             : 
    2923             :         // if name has been changed before creating the stream: set name!
    2924           0 :         pRet->m_aName = pElement->m_aOriginalName;
    2925           0 :         pElement->m_xStorage = pRet;
    2926             :     }
    2927             : 
    2928           0 :     if ( pRet )
    2929           0 :         pRet->Init();
    2930             : 
    2931           0 :     return pRet;
    2932             : }
    2933             : 
    2934           0 : bool UCBStorage::IsStorage( const OUString& rEleName ) const
    2935             : {
    2936           0 :     if( rEleName.isEmpty() )
    2937           0 :         return false;
    2938             : 
    2939           0 :     const UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
    2940           0 :     return ( pElement && pElement->m_bIsStorage );
    2941             : }
    2942             : 
    2943        4012 : bool UCBStorage::IsStream( const OUString& rEleName ) const
    2944             : {
    2945        4012 :     if( rEleName.isEmpty() )
    2946           0 :         return false;
    2947             : 
    2948        4012 :     const UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
    2949        4012 :     return ( pElement && !pElement->m_bIsStorage );
    2950             : }
    2951             : 
    2952           0 : bool UCBStorage::IsContained( const OUString & rEleName ) const
    2953             : {
    2954           0 :     if( rEleName.isEmpty() )
    2955           0 :         return false;
    2956           0 :     const UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
    2957           0 :     return ( pElement != NULL );
    2958             : }
    2959             : 
    2960           0 : bool UCBStorage::Remove( const OUString& rEleName )
    2961             : {
    2962           0 :     if( rEleName.isEmpty() )
    2963           0 :         return false;
    2964             : 
    2965           0 :     UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
    2966           0 :     if ( pElement )
    2967             :     {
    2968           0 :         pElement->m_bIsRemoved = true;
    2969             :     }
    2970             :     else
    2971           0 :         SetError( SVSTREAM_FILE_NOT_FOUND );
    2972             : 
    2973           0 :     return ( pElement != NULL );
    2974             : }
    2975             : 
    2976           0 : bool UCBStorage::Rename( const OUString& rEleName, const OUString& rNewName )
    2977             : {
    2978           0 :     if( rEleName.isEmpty()|| rNewName.isEmpty() )
    2979           0 :         return false;
    2980             : 
    2981           0 :     UCBStorageElement_Impl *pAlreadyExisting = FindElement_Impl( rNewName );
    2982           0 :     if ( pAlreadyExisting )
    2983             :     {
    2984           0 :         SetError( SVSTREAM_ACCESS_DENIED );
    2985           0 :         return false;                       // can't change to a name that is already used
    2986             :     }
    2987             : 
    2988           0 :     UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
    2989           0 :     if ( pElement )
    2990             :     {
    2991           0 :         pElement->m_aName = rNewName;
    2992             :     }
    2993             :     else
    2994           0 :         SetError( SVSTREAM_FILE_NOT_FOUND );
    2995             : 
    2996           0 :     return pElement != NULL;
    2997             : }
    2998             : 
    2999           0 : bool UCBStorage::MoveTo( const OUString& rEleName, BaseStorage* pNewSt, const OUString& rNewName )
    3000             : {
    3001           0 :     if( rEleName.isEmpty() || rNewName.isEmpty() )
    3002           0 :         return false;
    3003             : 
    3004           0 :     if ( pNewSt == static_cast<BaseStorage*>(this) && !FindElement_Impl( rNewName ) )
    3005             :     {
    3006           0 :         return Rename( rEleName, rNewName );
    3007             :     }
    3008             :     else
    3009             :     {
    3010             : /*
    3011             :         if ( PTR_CAST( UCBStorage, pNewSt ) )
    3012             :         {
    3013             :             // because the element is moved, not copied, a special optimization is possible :
    3014             :             // first copy the UCBStorageElement; flag old element as "Removed" and new as "Inserted",
    3015             :             // clear original name/type of the new element
    3016             :             // if moved element is open: copy content, but change absolute URL ( and those of all children of the element! ),
    3017             :             // clear original name/type of new content, keep the old original stream/storage, but forget its working streams,
    3018             :                 // close original UCBContent and original stream, only the TempFile and its stream may remain unchanged, but now
    3019             :             // belong to the new content
    3020             :             // if original and editable stream are identical ( readonly element ), it has to be copied to the editable
    3021             :             // stream of the destination object
    3022             :             // Not implemented at the moment ( risky?! ), perhaps later
    3023             :         }
    3024             : */
    3025             :         // MoveTo is done by first copying to the new destination and then removing the old element
    3026           0 :         bool bRet = CopyTo( rEleName, pNewSt, rNewName );
    3027           0 :         if ( bRet )
    3028           0 :             bRet = Remove( rEleName );
    3029           0 :         return bRet;
    3030             :     }
    3031             : }
    3032             : 
    3033           0 : bool UCBStorage::ValidateFAT()
    3034             : {
    3035             :     // ???
    3036           0 :     return true;
    3037             : }
    3038             : 
    3039           0 : bool UCBStorage::Validate( bool  bWrite ) const
    3040             : {
    3041             :     // ???
    3042           0 :     return ( !bWrite || ( pImp->m_nMode & StreamMode::WRITE ) );
    3043             : }
    3044             : 
    3045           0 : bool UCBStorage::ValidateMode( StreamMode m ) const
    3046             : {
    3047             :     // ???
    3048           0 :     if( m == ( StreamMode::READ | StreamMode::TRUNC ) )  // from stg.cxx
    3049           0 :         return true;
    3050             :     // only SHARE_DENYALL allowed
    3051             :     // storages open in r/o mode are OK, since only
    3052             :     // the commit may fail
    3053           0 :     if( m & StreamMode::SHARE_DENYALL )
    3054           0 :         return true;
    3055             : 
    3056           0 :     return true;
    3057             : }
    3058             : 
    3059           0 : const SvStream* UCBStorage::GetSvStream() const
    3060             : {
    3061             :     // this would cause a complete download of the file
    3062             :     // as it looks, this method is NOT used inside of SOT, only exported by class SotStorage - but for what ???
    3063           0 :     return pImp->m_pSource;
    3064             : }
    3065             : 
    3066           0 : bool UCBStorage::Equals( const BaseStorage& rStorage ) const
    3067             : {
    3068             :     // ???
    3069           0 :     return static_cast<BaseStorage const *>(this) == &rStorage;
    3070             : }
    3071             : 
    3072        2545 : bool UCBStorage::IsStorageFile( SvStream* pFile )
    3073             : {
    3074        2545 :     if ( !pFile )
    3075           0 :         return false;
    3076             : 
    3077        2545 :     sal_uLong nPos = pFile->Tell();
    3078        2545 :     pFile->Seek( STREAM_SEEK_TO_END );
    3079        2545 :     if ( pFile->Tell() < 4 )
    3080         122 :         return false;
    3081             : 
    3082        2423 :     pFile->Seek(0);
    3083        2423 :     sal_uInt32 nBytes(0);
    3084        2423 :     pFile->ReadUInt32( nBytes );
    3085             : 
    3086             :     // search for the magic bytes
    3087        2423 :     bool bRet = ( nBytes == 0x04034b50 );
    3088        2423 :     if ( !bRet )
    3089             :     {
    3090             :         // disk spanned file have an additional header in front of the usual one
    3091        2304 :         bRet = ( nBytes == 0x08074b50 );
    3092        2304 :         if ( bRet )
    3093             :         {
    3094           0 :             nBytes = 0;
    3095           0 :             pFile->ReadUInt32( nBytes );
    3096           0 :             bRet = ( nBytes == 0x04034b50 );
    3097             :         }
    3098             :     }
    3099             : 
    3100        2423 :     pFile->Seek( nPos );
    3101        2423 :     return bRet;
    3102             : }
    3103             : 
    3104          30 : OUString UCBStorage::GetLinkedFile( SvStream &rStream )
    3105             : {
    3106          30 :     OUString aString;
    3107          30 :     sal_uLong nPos = rStream.Tell();
    3108          30 :     rStream.Seek( STREAM_SEEK_TO_END );
    3109          30 :     if ( !rStream.Tell() )
    3110           0 :         return aString;
    3111             : 
    3112          30 :     rStream.Seek(0);
    3113             :     sal_uInt32 nBytes;
    3114          30 :     rStream.ReadUInt32( nBytes );
    3115          30 :     if( nBytes == 0x04034b50 )
    3116             :     {
    3117          30 :         OString aTmp = read_uInt16_lenPrefixed_uInt8s_ToOString(rStream);
    3118          30 :         if (aTmp.match("ContentURL="))
    3119             :         {
    3120           0 :             aString = OStringToOUString(aTmp.copy(11), RTL_TEXTENCODING_UTF8);
    3121          30 :         }
    3122             :     }
    3123             : 
    3124          30 :     rStream.Seek( nPos );
    3125          30 :     return aString;
    3126             : }
    3127             : 
    3128             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11