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

Generated by: LCOV version 1.10