LCOV - code coverage report
Current view: top level - libreoffice/sot/source/sdstor - stg.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 363 563 64.5 %
Date: 2012-12-27 Functions: 60 93 64.5 %
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             : 
      21             : #include <sot/storinfo.hxx>
      22             : #include <osl/file.hxx>
      23             : #include <tools/tempfile.hxx>
      24             : #include <tools/string.hxx>
      25             : #include <tools/fsys.hxx>
      26             : #include <tools/stream.hxx>
      27             : #include <tools/debug.hxx>
      28             : 
      29             : #include "sot/stg.hxx"
      30             : #include "stgelem.hxx"
      31             : #include "stgcache.hxx"
      32             : #include "stgstrms.hxx"
      33             : #include "stgdir.hxx"
      34             : #include "stgio.hxx"
      35             : #include "stgole.hxx"
      36             : 
      37             : static long nTmpCount = 0;
      38             : 
      39             : // The internal open mode is STREAM_READ | STREAM_TRUNC, which is silly
      40             : // by itself. It inhibits the checking of sharing modes and is used
      41             : // during CopyTo() and MoveTo() for opening a stream in read mode
      42             : // although it may be open in DENYALL mode
      43             : 
      44             : #define INTERNAL_MODE ( STREAM_READ | STREAM_TRUNC )
      45             : 
      46             : ///////////////////////// class StorageBase //////////////////////////////
      47             : 
      48         194 : TYPEINIT0( StorageBase );
      49           0 : TYPEINIT1( BaseStorageStream, StorageBase );
      50         194 : TYPEINIT1( BaseStorage, StorageBase );
      51             : 
      52        1338 : StorageBase::StorageBase()
      53        1338 :     : m_bAutoCommit( sal_False )
      54             : {
      55        1338 :     m_nMode  = STREAM_READ;
      56        1338 :     m_nError = SVSTREAM_OK;
      57        1338 : }
      58             : 
      59        1338 : StorageBase::~StorageBase()
      60             : {
      61        1338 : }
      62             : 
      63             : // The following three methods are declared as const, since they
      64             : // may be called from within a const method.
      65             : 
      66     1702341 : sal_uLong StorageBase::GetError() const
      67             : {
      68     1702341 :     sal_uLong n = m_nError;
      69     1702341 :     ((StorageBase*) this)->m_nError = SVSTREAM_OK;
      70     1702341 :     return n;
      71             : }
      72             : 
      73        1594 : void StorageBase::SetError( sal_uLong n ) const
      74             : {
      75        1594 :     if( !m_nError )
      76        1591 :         ((StorageBase*) this)->m_nError = n;
      77        1594 : }
      78             : 
      79        1316 : void StorageBase::ResetError() const
      80             : {
      81        1316 :     ((StorageBase*) this)->m_nError = SVSTREAM_OK;
      82        1316 : }
      83             : 
      84             : // Retrieve the underlying SvStream for info purposes
      85             : 
      86           0 : const SvStream* OLEStorageBase::GetSvStream_Impl() const
      87             : {
      88           0 :     return pIo ? pIo->GetStrm() : NULL;
      89             : }
      90             : 
      91        1095 : OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
      92        1095 :     : nStreamMode( nMode ), pIo( p ), pEntry( pe )
      93             : {
      94        1095 :     if ( p )
      95        1095 :         p->IncRef();
      96        1095 :     if( pe )
      97         960 :         pe->nRefCnt++;
      98        1095 : }
      99             : 
     100        1095 : OLEStorageBase::~OLEStorageBase()
     101             : {
     102        1095 :     if( pEntry )
     103             :     {
     104             :         DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" );
     105        1059 :         if( !--pEntry->nRefCnt )
     106             :         {
     107        1056 :             if( pEntry->bZombie )
     108           0 :                 delete pEntry;
     109             :             else
     110        1056 :                 pEntry->Close();
     111             :         }
     112             : 
     113        1059 :         pEntry = NULL;
     114             :     }
     115             : 
     116             : 
     117        1095 :     if( pIo && !pIo->DecRef() )
     118             :     {
     119         102 :         delete pIo;
     120         102 :         pIo = NULL;
     121             :     }
     122        1095 : }
     123             : 
     124             : // Validate the instance for I/O
     125             : 
     126     1710777 : sal_Bool OLEStorageBase::Validate_Impl( sal_Bool bWrite ) const
     127             : {
     128     3422174 :     if( pIo
     129             :         && pIo->pTOC
     130             :         && pEntry
     131     1710745 :         && !pEntry->bInvalid
     132         652 :         &&  ( !bWrite || !pEntry->bDirect || ( nStreamMode & STREAM_WRITE ) ) )
     133     1710745 :             return sal_True;
     134          32 :     return sal_False;
     135             : }
     136             : 
     137        1707 : sal_Bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p ) const
     138             : {
     139        1707 :     if( m == INTERNAL_MODE )
     140         258 :         return sal_True;
     141        1449 :     sal_uInt16 nCurMode = ( p && p->nRefCnt ) ? p->nMode : 0xFFFF;
     142        1449 :     if( ( m & 3 ) == STREAM_READ )
     143             :     {
     144             :         // only SHARE_DENYWRITE or SHARE_DENYALL allowed
     145         897 :         if( ( ( m & STREAM_SHARE_DENYWRITE )
     146             :            && ( nCurMode & STREAM_SHARE_DENYWRITE ) )
     147             :          || ( ( m & STREAM_SHARE_DENYALL )
     148             :            && ( nCurMode & STREAM_SHARE_DENYALL ) ) )
     149         897 :             return sal_True;
     150             :     }
     151             :     else
     152             :     {
     153             :         // only SHARE_DENYALL allowed
     154             :         // storages open in r/o mode are OK, since only
     155             :         // the commit may fail
     156         552 :         if( ( m & STREAM_SHARE_DENYALL )
     157             :          && ( nCurMode & STREAM_SHARE_DENYALL ) )
     158         552 :             return sal_True;
     159             :     }
     160           0 :     return sal_False;
     161             : }
     162             : 
     163             : 
     164             : //////////////////////// class StorageStream /////////////////////////////
     165             : 
     166         500 : TYPEINIT1( StorageStream, BaseStorageStream );
     167             : 
     168         956 : StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
     169         956 :              : OLEStorageBase( p, q, m_nMode ), nPos( 0L )
     170             : {
     171             :     // The dir entry may be 0; this means that the stream is invalid.
     172         956 :     if( q && p )
     173             :     {
     174        1846 :         if( q->nRefCnt == 1 )
     175             :         {
     176         920 :             q->nMode = m;
     177         920 :             q->OpenStream( *p );
     178             :         }
     179             :     }
     180             :     else
     181          33 :         m &= ~STREAM_READWRITE;
     182         956 :     m_nMode = m;
     183         956 : }
     184             : 
     185        2868 : StorageStream::~StorageStream()
     186             : {
     187             :     // Do an auto-commit if the entry is open in direct mode
     188         956 :     if( m_bAutoCommit )
     189         896 :         Commit();
     190         956 :     if( pEntry && pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
     191           3 :         pEntry->Commit();
     192        1912 : }
     193             : 
     194         125 : sal_Bool StorageStream::Equals( const BaseStorageStream& rStream ) const
     195             : {
     196         125 :     const StorageStream* pOther = PTR_CAST( StorageStream, &rStream );
     197         125 :     return pOther && ( pOther->pEntry == pEntry );
     198             : }
     199             : 
     200      951777 : sal_uLong StorageStream::Read( void* pData, sal_uLong nSize )
     201             : {
     202      951777 :     if( Validate() )
     203             :     {
     204      951751 :         pEntry->Seek( nPos );
     205      951751 :         nSize = pEntry->Read( pData, (sal_Int32) nSize );
     206      951751 :         pIo->MoveError( *this );
     207      951751 :         nPos += nSize;
     208             :     }
     209             :     else
     210          26 :         nSize = 0L;
     211      951777 :     return nSize;
     212             : }
     213             : 
     214         259 : sal_uLong StorageStream::Write( const void* pData, sal_uLong nSize )
     215             : {
     216         259 :     if( Validate( sal_True ) )
     217             :     {
     218         259 :         pEntry->Seek( nPos );
     219         259 :         nSize = pEntry->Write( pData, (sal_Int32) nSize );
     220         259 :         pIo->MoveError( *this );
     221         259 :         nPos += nSize;
     222             :     }
     223             :     else
     224           0 :         nSize = 0L;
     225         259 :     return nSize;
     226             : }
     227             : 
     228      748434 : sal_uLong StorageStream::Seek( sal_uLong n )
     229             : {
     230      748434 :     if( Validate() )
     231      748430 :         return nPos = pEntry->Seek( n );
     232             :     else
     233           4 :         return n;
     234             : }
     235             : 
     236         137 : void StorageStream::Flush()
     237             : {
     238             :     // Flushing means committing, since streams are never transacted
     239         137 :     Commit();
     240         137 : }
     241             : 
     242         125 : sal_Bool StorageStream::SetSize( sal_uLong nNewSize )
     243             : {
     244         125 :     if( Validate( sal_True ) )
     245             :     {
     246         125 :         sal_Bool b = pEntry->SetSize( (sal_Int32) nNewSize );
     247         125 :         pIo->MoveError( *this );
     248         125 :         return b;
     249             :     }
     250             :     else
     251           0 :         return sal_False;
     252             : }
     253             : 
     254        6502 : sal_uLong StorageStream::GetSize() const
     255             : {
     256        6502 :     if( Validate() )
     257        6502 :         return pEntry->GetSize();
     258           0 :     return 0;
     259             : }
     260             : 
     261        1283 : sal_Bool StorageStream::Commit()
     262             : {
     263        1283 :     if( !Validate() )
     264           0 :         return sal_False;
     265        1283 :     if( !( m_nMode & STREAM_WRITE ) )
     266             :     {
     267         533 :         SetError( SVSTREAM_ACCESS_DENIED );
     268         533 :         return sal_False;
     269             :     }
     270             :     else
     271             :     {
     272         750 :         pEntry->Commit();
     273         750 :         pIo->MoveError( *this );
     274         750 :         return Good();
     275             :     }
     276             : }
     277             : 
     278           0 : sal_Bool StorageStream::Revert()
     279             : {
     280           0 :     sal_Bool bResult = sal_False;
     281             : 
     282           0 :     if ( Validate() )
     283             :     {
     284           0 :         pEntry->Revert();
     285           0 :         pIo->MoveError( *this );
     286           0 :         bResult = Good();
     287             :     }
     288             : 
     289           0 :     return bResult;
     290             : }
     291             : 
     292         125 : sal_Bool StorageStream::CopyTo( BaseStorageStream* pDest )
     293             : {
     294         125 :     if( !Validate() || !pDest || !pDest->Validate( sal_True ) || Equals( *pDest ) )
     295           0 :         return sal_False;
     296         125 :     pEntry->Copy( *pDest );
     297         125 :     pDest->Commit();
     298         125 :     pIo->MoveError( *this );
     299         125 :     SetError( pDest->GetError() );
     300         125 :     return sal_Bool( Good() && pDest->Good() );
     301             : }
     302             : 
     303           0 : const SvStream* StorageStream::GetSvStream() const
     304             : {
     305           0 :     return GetSvStream_Impl();
     306             : }
     307             : 
     308     1708630 : sal_Bool StorageStream::Validate( sal_Bool bValidate ) const
     309             : {
     310     1708630 :     sal_Bool bRet = Validate_Impl( bValidate );
     311     1708630 :     if ( !bRet )
     312          30 :         SetError( SVSTREAM_ACCESS_DENIED );
     313     1708630 :     return bRet;
     314             : }
     315             : 
     316           0 : sal_Bool StorageStream::ValidateMode( StreamMode nMode ) const
     317             : {
     318           0 :     sal_Bool bRet = ValidateMode_Impl( nMode, NULL );
     319           0 :     if ( !bRet )
     320           0 :         SetError( SVSTREAM_ACCESS_DENIED );
     321           0 :     return bRet;
     322             : }
     323             : 
     324             : ///////////////////////// class SvStorageInfo //////////////////////////////
     325             : 
     326         951 : SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
     327             : {
     328         951 :     rE.aEntry.GetName( aName );
     329         951 :     bStorage = sal_Bool( rE.aEntry.GetType() == STG_STORAGE );
     330         951 :     bStream  = sal_Bool( rE.aEntry.GetType() == STG_STREAM );
     331         951 :     nSize    = bStorage ? 0 : rE.aEntry.GetSize();
     332         951 : }
     333             : 
     334             : /////////////////////////// class Storage ////////////////////////////////
     335             : 
     336           0 : sal_Bool Storage::IsStorageFile( const String & rFileName )
     337             : {
     338           0 :     StgIo aIo;
     339           0 :     if( aIo.Open( rFileName, STREAM_STD_READ ) )
     340           0 :         return aIo.Load();
     341           0 :     return sal_False;
     342             : }
     343             : 
     344         410 : sal_Bool Storage::IsStorageFile( SvStream* pStream )
     345             : {
     346         410 :     sal_Bool bRet = sal_False;
     347             : 
     348         410 :     if ( pStream )
     349             :     {
     350         410 :         StgHeader aHdr;
     351         410 :         sal_uLong nPos = pStream->Tell();
     352         410 :         bRet = ( aHdr.Load( *pStream ) && aHdr.Check() );
     353             : 
     354             :         // It's not a stream error if it is too small for a OLE storage header
     355         410 :         if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK )
     356           0 :             pStream->ResetError();
     357         410 :         pStream->Seek( nPos );
     358             :     }
     359             : 
     360         410 :     return bRet;
     361             : }
     362             : 
     363             : // Open the storage file. If writing is permitted and the file is not
     364             : // a storage file, initialize it.
     365             : 
     366         347 : TYPEINIT1( Storage, BaseStorage );
     367             : 
     368           0 : Storage::Storage( const String& rFile, StreamMode m, sal_Bool bDirect )
     369           0 :        : OLEStorageBase( new StgIo, NULL, m_nMode ), aName( rFile ), bIsRoot( sal_False )
     370             : {
     371           0 :     sal_Bool bTemp = sal_False;
     372           0 :     if( !aName.Len() )
     373             :     {
     374             :         // no name = temporary name!
     375           0 :         aName = TempFile::CreateTempName();
     376           0 :         bTemp = sal_True;
     377             :     }
     378             :     // the root storage creates the I/O system
     379           0 :     m_nMode = m;
     380           0 :     if( pIo->Open( aName, m ) )
     381             :     {
     382           0 :         Init( sal_Bool( ( m & ( STREAM_TRUNC | STREAM_NOCREATE ) ) == STREAM_TRUNC ) );
     383           0 :         if( pEntry )
     384             :         {
     385           0 :             pEntry->bDirect = bDirect;
     386           0 :             pEntry->nMode = m;
     387           0 :             pEntry->bTemp = bTemp;
     388             :         }
     389             :     }
     390             :     else
     391             :     {
     392           0 :         pIo->MoveError( *this );
     393           0 :         pEntry = NULL;
     394             :     }
     395           0 : }
     396             : 
     397             : // Create a storage on a given stream.
     398             : 
     399         102 : Storage::Storage( SvStream& r, sal_Bool bDirect )
     400         102 :        : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( sal_False )
     401             : {
     402         102 :     m_nMode = STREAM_READ;
     403         102 :     if( r.IsWritable() )
     404          98 :         m_nMode = STREAM_READ | STREAM_WRITE;
     405         102 :     if( r.GetError() == SVSTREAM_OK )
     406             :     {
     407         102 :         pIo->SetStrm( &r, sal_False );
     408         102 :         sal_uLong nSize = r.Seek( STREAM_SEEK_TO_END );
     409         102 :         r.Seek( 0L );
     410             :         // Initializing is OK if the stream is empty
     411         102 :         Init( sal_Bool( nSize == 0 ) );
     412         102 :         if( pEntry )
     413             :         {
     414          99 :             pEntry->bDirect = bDirect;
     415          99 :             pEntry->nMode = m_nMode;
     416             :         }
     417         102 :         pIo->MoveError( *this );
     418             :     }
     419             :     else
     420             :     {
     421           0 :         SetError( r.GetError() );
     422           0 :         pEntry = NULL;
     423             :     }
     424         102 : }
     425             : 
     426             : 
     427           0 : Storage::Storage( UCBStorageStream& rStrm, sal_Bool bDirect )
     428           0 :        : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( sal_False )
     429             : {
     430           0 :     m_nMode = STREAM_READ;
     431             : 
     432           0 :     if ( rStrm.GetError() != SVSTREAM_OK )
     433             :     {
     434           0 :         SetError( rStrm.GetError() );
     435           0 :         pEntry = NULL;
     436           0 :         return;
     437             :     }
     438             : 
     439           0 :     SvStream* pStream = rStrm.GetModifySvStream();
     440           0 :     if ( !pStream )
     441             :     {
     442             :         OSL_FAIL( "UCBStorageStream can not provide SvStream implementation!\n" );
     443           0 :         SetError( SVSTREAM_GENERALERROR );
     444           0 :         pEntry = NULL;
     445           0 :         return;
     446             :     }
     447             : 
     448           0 :     if( pStream->IsWritable() )
     449           0 :         m_nMode = STREAM_READ | STREAM_WRITE;
     450             : 
     451           0 :     pIo->SetStrm( &rStrm );
     452             : 
     453           0 :     sal_uLong nSize = pStream->Seek( STREAM_SEEK_TO_END );
     454           0 :     pStream->Seek( 0L );
     455             :     // Initializing is OK if the stream is empty
     456           0 :     Init( sal_Bool( nSize == 0 ) );
     457           0 :     if( pEntry )
     458             :     {
     459           0 :         pEntry->bDirect = bDirect;
     460           0 :         pEntry->nMode = m_nMode;
     461             :     }
     462             : 
     463           0 :     pIo->MoveError( *this );
     464             : }
     465             : 
     466             : 
     467             : // Perform common code for both ctors above.
     468             : 
     469         102 : void Storage::Init( sal_Bool bCreate )
     470             : {
     471         102 :     pEntry = NULL;
     472         102 :     sal_Bool bHdrLoaded = sal_False;
     473         102 :     bIsRoot = sal_True;
     474             : 
     475             :     OSL_ENSURE( pIo, "The pointer may not be empty at this point!" );
     476         102 :     if( pIo->Good() && pIo->GetStrm() )
     477             :     {
     478         102 :         sal_uLong nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END );
     479         102 :         pIo->GetStrm()->Seek( 0L );
     480         102 :         if( nSize )
     481             :         {
     482          86 :             bHdrLoaded = pIo->Load();
     483          86 :             if( !bHdrLoaded && !bCreate  )
     484             :             {
     485             :                 // File is not a storage and not empty; do not destroy!
     486           3 :                 SetError( SVSTREAM_FILEFORMAT_ERROR );
     487         105 :                 return;
     488             :             }
     489             :         }
     490             :     }
     491             :     // file is a storage, empty or should be overwritten
     492          99 :     pIo->ResetError();
     493             :     // we have to set up the data structures, since
     494             :     // the file is empty
     495          99 :     if( !bHdrLoaded )
     496          16 :         pIo->Init();
     497          99 :     if( pIo->Good() && pIo->pTOC )
     498             :     {
     499          99 :         pEntry = pIo->pTOC->GetRoot();
     500          99 :         pEntry->nRefCnt++;
     501             :     }
     502             : }
     503             : 
     504             : // Internal ctor
     505             : 
     506          37 : Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
     507          37 :        : OLEStorageBase( p, q, m_nMode ), bIsRoot( sal_False )
     508             : {
     509          37 :     if( q )
     510          37 :         q->aEntry.GetName( aName );
     511             :     else
     512           0 :         m &= ~STREAM_READWRITE;
     513          37 :     m_nMode   = m;
     514          37 :     if( q && q->nRefCnt == 1 )
     515          37 :         q->nMode = m;
     516          37 : }
     517             : 
     518         417 : Storage::~Storage()
     519             : {
     520             :     // Invalidate all open substorages
     521         139 :     if( m_bAutoCommit )
     522          32 :         Commit();
     523         139 :     if( pEntry )
     524             :     {
     525             :         // Do an auto-commit if the entry is open in direct mode
     526         136 :         if( pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
     527           3 :             Commit();
     528         136 :         if( pEntry->nRefCnt == 1 )
     529         136 :             pEntry->Invalidate();
     530             :     }
     531             :     // close the stream is root storage
     532         139 :     if( bIsRoot )
     533         102 :         pIo->Close();
     534             :     // remove the file if temporary root storage
     535         139 :     if( bIsRoot && pEntry && pEntry->bTemp )
     536             :     {
     537           0 :         osl::File::remove( GetName() );
     538             :     }
     539         278 : }
     540             : 
     541          22 : const String& Storage::GetName() const
     542             : {
     543          22 :     if( !bIsRoot && Validate() )
     544          19 :         pEntry->aEntry.GetName( ((Storage*) this)->aName );
     545          22 :     return aName;
     546             : }
     547             : 
     548             : // Fill in the info list for this storage
     549             : 
     550         107 : void Storage::FillInfoList( SvStorageInfoList* pList ) const
     551             : {
     552         107 :     if( Validate() && pList )
     553             :     {
     554         107 :         StgIterator aIter( *pEntry );
     555         107 :         StgDirEntry* p = aIter.First();
     556        1165 :         while( p )
     557             :         {
     558         951 :             if( !p->bInvalid )
     559             :             {
     560         951 :                 SvStorageInfo aInfo( *p );
     561         951 :                 pList->push_back( aInfo );
     562             :             }
     563         951 :             p = aIter.Next();
     564             :         }
     565             :     }
     566         107 : }
     567             : 
     568             : // Open or create a substorage
     569             : 
     570           0 : BaseStorage* Storage::OpenUCBStorage( const String& rName, StreamMode m, sal_Bool bDirect )
     571             : {
     572             :     OSL_FAIL("Not supported!");
     573           0 :     return OpenStorage( rName, m, bDirect );
     574             : }
     575             : 
     576           4 : BaseStorage* Storage::OpenOLEStorage( const String& rName, StreamMode m, sal_Bool bDirect )
     577             : {
     578           4 :     return OpenStorage( rName, m, bDirect );
     579             : }
     580             : 
     581          37 : BaseStorage* Storage::OpenStorage( const String& rName, StreamMode m, sal_Bool bDirect )
     582             : {
     583          37 :     if( !Validate() || !ValidateMode( m ) )
     584           0 :         return new Storage( pIo, NULL, m );
     585          37 :     if( bDirect && !pEntry->bDirect )
     586           0 :         bDirect = sal_False;
     587             : 
     588          37 :     StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
     589          37 :     if( !p )
     590             :     {
     591           7 :         if( !( m & STREAM_NOCREATE ) )
     592             :         {
     593           7 :             sal_Bool bTemp = sal_False;
     594             :             // create a new storage
     595           7 :             String aNewName = rName;
     596           7 :             if( !aNewName.Len() )
     597             :             {
     598           0 :                 aNewName.AssignAscii( "Temp Stg " );
     599           0 :                 aNewName.Append( String::CreateFromInt32( ++nTmpCount ) );
     600           0 :                 bTemp = sal_True;
     601             :             }
     602           7 :             p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE );
     603           7 :             if( p )
     604           7 :                 p->bTemp = bTemp;
     605             :         }
     606           7 :         if( !p )
     607             :             pIo->SetError( ( m & STREAM_WRITE )
     608           0 :                              ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
     609             :     }
     610          30 :     else if( !ValidateMode( m, p ) )
     611           0 :         p = NULL;
     612          37 :     if( p && p->aEntry.GetType() != STG_STORAGE )
     613             :     {
     614           0 :         pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
     615           0 :         p = NULL;
     616             :     }
     617             : 
     618             :     // Either direct or transacted mode is supported
     619          37 :     if( p && pEntry->nRefCnt == 1 )
     620          37 :         p->bDirect = bDirect;
     621             : 
     622             :     // Dont check direct conflict if opening readonly
     623          37 :     if( p && (m & STREAM_WRITE ))
     624             :     {
     625          32 :         if( p->bDirect != bDirect )
     626           0 :             SetError( SVSTREAM_ACCESS_DENIED );
     627             :     }
     628          37 :     Storage* pStg = new Storage( pIo, p, m );
     629          37 :     pIo->MoveError( *pStg );
     630          37 :     if( m & STREAM_WRITE ) pStg->m_bAutoCommit = sal_True;
     631          37 :     return pStg;
     632             : }
     633             : 
     634             : // Open a stream
     635             : 
     636         956 : BaseStorageStream* Storage::OpenStream( const String& rName, StreamMode m, sal_Bool,
     637             : const rtl::OString*
     638             : #ifdef DBG_UTIL
     639             : pB
     640             : #endif
     641             : )
     642             : {
     643             :     DBG_ASSERT(!pB, "Encryption not supported");
     644             : 
     645         956 :     if( !Validate() || !ValidateMode( m ) )
     646           2 :         return new StorageStream( pIo, NULL, m );
     647         954 :     StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
     648         954 :     sal_Bool bTemp = sal_False;
     649         954 :     if( !p )
     650             :     {
     651         268 :         if( !( m & STREAM_NOCREATE ) )
     652             :         {
     653             :             // create a new stream
     654             :             // make a name if the stream is temporary (has no name)
     655         237 :             String aNewName( rName );
     656         237 :             if( !aNewName.Len() )
     657             :             {
     658           0 :                 aNewName.AssignAscii( "Temp Strm " );
     659           0 :                 aNewName.Append( String::CreateFromInt32( ++nTmpCount ) );
     660           0 :                 bTemp = sal_True;
     661             :             }
     662         237 :             p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM );
     663             :         }
     664         268 :         if( !p )
     665             :             pIo->SetError( ( m & STREAM_WRITE )
     666          31 :                            ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
     667             :     }
     668         686 :     else if( !ValidateMode( m, p ) )
     669           0 :         p = NULL;
     670         954 :     if( p && p->aEntry.GetType() != STG_STREAM )
     671             :     {
     672           0 :         pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
     673           0 :         p = NULL;
     674             :     }
     675         954 :     if( p )
     676             :     {
     677         923 :         p->bTemp = bTemp;
     678         923 :         p->bDirect = pEntry->bDirect;
     679             :     }
     680         954 :     StorageStream* pStm = new StorageStream( pIo, p, m );
     681         954 :     if( p && !p->bDirect )
     682         896 :         pStm->SetAutoCommit( sal_True );
     683         954 :     pIo->MoveError( *pStm );
     684         954 :     return pStm;
     685             : }
     686             : 
     687             : // Delete a stream or substorage by setting the temp bit.
     688             : 
     689           0 : sal_Bool Storage::Remove( const String& rName )
     690             : {
     691           0 :     if( !Validate( sal_True ) )
     692           0 :         return sal_False;
     693           0 :     StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
     694           0 :     if( p )
     695             :     {
     696           0 :         p->Invalidate( sal_True );
     697           0 :         return sal_True;
     698             :     }
     699             :     else
     700             :     {
     701           0 :         SetError( SVSTREAM_FILE_NOT_FOUND );
     702           0 :         return sal_False;
     703             :     }
     704             : }
     705             : 
     706             : // Rename a storage element
     707             : 
     708           0 : sal_Bool Storage::Rename( const String& rOld, const String& rNew )
     709             : {
     710           0 :     if( Validate( sal_True ) )
     711             :     {
     712           0 :         sal_Bool b = pIo->pTOC->Rename( *pEntry, rOld, rNew );
     713           0 :         pIo->MoveError( *this );
     714           0 :         return b;
     715             :     }
     716             :     else
     717           0 :         return sal_False;
     718             : }
     719             : 
     720             : // Copy one element
     721             : 
     722         129 : sal_Bool Storage::CopyTo( const String& rElem, BaseStorage* pDest, const String& rNew )
     723             : {
     724         129 :     if( !Validate() || !pDest || !pDest->Validate( sal_True ) )
     725           0 :         return sal_False;
     726         129 :     StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
     727         129 :     if( pElem )
     728             :     {
     729         129 :         if( pElem->aEntry.GetType() == STG_STORAGE )
     730             :         {
     731             :             // copy the entire storage
     732           4 :             BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE );
     733           4 :             BaseStorage* p2 = pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
     734             : 
     735           4 :             if ( p2 )
     736             :             {
     737           4 :                 sal_uLong nTmpErr = p2->GetError();
     738           4 :                 if( !nTmpErr )
     739             :                 {
     740           4 :                     p2->SetClassId( p1->GetClassId() );
     741           4 :                     p1->CopyTo( p2 );
     742           4 :                     SetError( p1->GetError() );
     743             : 
     744           4 :                     nTmpErr = p2->GetError();
     745           4 :                     if( !nTmpErr )
     746           4 :                         p2->Commit();
     747             :                     else
     748           0 :                         pDest->SetError( nTmpErr );
     749             :                 }
     750             :                 else
     751           0 :                     pDest->SetError( nTmpErr );
     752             :             }
     753             : 
     754           4 :             delete p1;
     755           4 :             delete p2;
     756           4 :             return sal_Bool( Good() && pDest->Good() );
     757             :         }
     758             :         else
     759             :         {
     760             :             // stream copy
     761         125 :             BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE );
     762         125 :             BaseStorageStream* p2 = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
     763             : 
     764         125 :             if ( p2 )
     765             :             {
     766         125 :                 sal_uLong nTmpErr = p2->GetError();
     767         125 :                 if( !nTmpErr )
     768             :                 {
     769         125 :                     p1->CopyTo( p2 );
     770         125 :                     SetError( p1->GetError() );
     771             : 
     772         125 :                     nTmpErr = p2->GetError();
     773         125 :                     if( !nTmpErr )
     774         125 :                         p2->Commit();
     775             :                     else
     776           0 :                         pDest->SetError( nTmpErr );
     777             :                 }
     778             :                 else
     779           0 :                     pDest->SetError( nTmpErr );
     780             :             }
     781             : 
     782         125 :             delete p1;
     783         125 :             delete p2;
     784         125 :             return sal_Bool( Good() && pDest->Good() );
     785             :         }
     786             :     }
     787           0 :     SetError( SVSTREAM_FILE_NOT_FOUND );
     788           0 :     return sal_False;
     789             : }
     790             : 
     791          14 : sal_Bool Storage::CopyTo( BaseStorage* pDest ) const
     792             : {
     793          14 :     if( !Validate() || !pDest || !pDest->Validate( sal_True ) || Equals( *pDest ) )
     794             :     {
     795           0 :         SetError( SVSTREAM_ACCESS_DENIED );
     796           0 :         return sal_False;
     797             :     }
     798          14 :     Storage* pThis = (Storage*) this;
     799          14 :     pDest->SetClassId( GetClassId() );
     800          14 :     pDest->SetDirty();
     801          14 :     SvStorageInfoList aList;
     802          14 :     FillInfoList( &aList );
     803          14 :     sal_Bool bRes = sal_True;
     804         143 :     for( size_t i = 0; i < aList.size() && bRes; i++ )
     805             :     {
     806         129 :         SvStorageInfo& rInfo = aList[ i ];
     807         129 :         bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() );
     808             :     }
     809          14 :     if( !bRes )
     810           0 :         SetError( pDest->GetError() );
     811          14 :     return sal_Bool( Good() && pDest->Good() );
     812             : }
     813             : 
     814             : // Move one element
     815             : 
     816           0 : sal_Bool Storage::MoveTo( const String& rElem, BaseStorage* pODest, const String& rNew )
     817             : {
     818           0 :     if( !Validate() || !pODest || !pODest->Validate( sal_True ) || Equals( *pODest ) )
     819             :     {
     820           0 :         SetError( SVSTREAM_ACCESS_DENIED );
     821           0 :         return sal_False;
     822             :     }
     823             : 
     824           0 :     StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
     825           0 :     if( pElem )
     826             :     {
     827             :         // Simplest case: both storages share the same file
     828             :         sal_Bool bRes;
     829           0 :         Storage *pOther = PTR_CAST( Storage, pODest );
     830           0 :         if( pOther && pIo == pOther->pIo && rElem == rNew )
     831             :         {
     832           0 :             Storage *p = (Storage*) pODest;
     833           0 :             Storage *pDest = p;
     834             :             // both storages are conventional storages, use implementation dependent code
     835           0 :             if( !pElem->IsContained( pDest->pEntry ) )
     836             :             {
     837             :                 // cyclic move
     838           0 :                 SetError( SVSTREAM_ACCESS_DENIED );
     839           0 :                 return sal_False;
     840             :             }
     841           0 :             bRes = pIo->pTOC->Move( *pEntry, *pDest->pEntry, rNew );
     842           0 :             if( !bRes )
     843             :             {
     844           0 :                 pIo->MoveError( *this );
     845           0 :                 pDest->pIo->MoveError( *pDest );
     846           0 :                 sal_uLong nErr = GetError();
     847           0 :                 if( !nErr )
     848           0 :                     nErr = pDest->GetError();
     849           0 :                 SetError( nErr );
     850           0 :                 pDest->SetError( nErr );
     851             :             }
     852             :         }
     853             :         else
     854             :         {
     855           0 :             bRes = CopyTo( rElem, pODest, rNew );
     856           0 :             if( bRes )
     857           0 :                 bRes = Remove( rElem );
     858             :         }
     859           0 :         if( !bRes )
     860           0 :             SetError( pIo->GetError() );
     861           0 :         return bRes;
     862             :     }
     863           0 :     SetError( SVSTREAM_FILE_NOT_FOUND );
     864           0 :     return sal_False;
     865             : }
     866             : 
     867         193 : sal_Bool Storage::IsStorage( const String& rName ) const
     868             : {
     869         193 :     if( Validate() )
     870             :     {
     871         193 :         StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
     872         193 :         if( p )
     873         193 :             return sal_Bool( p->aEntry.GetType() == STG_STORAGE );
     874             :     }
     875           0 :     return sal_False;
     876             : }
     877             : 
     878          33 : sal_Bool Storage::IsStream( const String& rName ) const
     879             : {
     880          33 :     if( Validate() )
     881             :     {
     882          33 :         StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
     883          33 :         if( p )
     884          27 :             return sal_Bool( p->aEntry.GetType() == STG_STREAM );
     885             :     }
     886           6 :     return sal_False;
     887             : }
     888             : 
     889         461 : sal_Bool Storage::IsContained( const String& rName ) const
     890             : {
     891         461 :     if( Validate() )
     892         461 :         return sal_Bool( pIo->pTOC->Find( *pEntry, rName ) != NULL );
     893             :     else
     894           0 :         return sal_False;
     895             : }
     896             : 
     897             : // Commit all sub-elements within this storage. If this is
     898             : // the root, commit the FAT, the TOC and the header as well.
     899             : 
     900          55 : sal_Bool Storage::Commit()
     901             : {
     902          55 :     sal_Bool bRes = sal_True;
     903          55 :     if( !Validate() )
     904           0 :         return sal_False;
     905          55 :     if( !( m_nMode & STREAM_WRITE ) )
     906             :     {
     907           0 :         SetError( SVSTREAM_ACCESS_DENIED );
     908           0 :         return sal_False;
     909             :     }
     910             :     else
     911             :     {
     912             :         // Also commit the sub-streams and Storages
     913          55 :         StgIterator aIter( *pEntry );
     914         513 :         for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() )
     915         458 :             bRes = p->Commit();
     916          55 :         if( bRes && bIsRoot )
     917             :         {
     918          19 :             bRes = pEntry->Commit();
     919          19 :             if( bRes )
     920          19 :                 bRes = pIo->CommitAll();
     921             :         }
     922          55 :         pIo->MoveError( *this );
     923             :     }
     924          55 :     return bRes;
     925             : }
     926             : 
     927           0 : sal_Bool Storage::Revert()
     928             : {
     929           0 :     return sal_True;
     930             : }
     931             : 
     932             : ///////////////////////////// OLE Support ////////////////////////////////
     933             : 
     934             : // Set the storage type
     935             : 
     936           0 : void Storage::SetClass( const SvGlobalName & rClass,
     937             :                                 sal_uLong nOriginalClipFormat,
     938             :                                 const String & rUserTypeName )
     939             : {
     940           0 :     if( Validate( sal_True ) )
     941             :     {
     942             :         // set the class name in the root entry
     943           0 :         pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() );
     944           0 :         pEntry->SetDirty();
     945             :         // then create the streams
     946           0 :         StgCompObjStream aCompObj( *this, sal_True );
     947           0 :         aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID();
     948           0 :         aCompObj.GetCbFormat() = nOriginalClipFormat;
     949           0 :         aCompObj.GetUserName() = rUserTypeName;
     950           0 :         if( !aCompObj.Store() )
     951           0 :             SetError( aCompObj.GetError() );
     952             :         else
     953             :         {
     954           0 :             StgOleStream aOle( *this, STREAM_WRITE );
     955           0 :             if( !aOle.Store() )
     956           0 :                 SetError( aOle.GetError() );
     957           0 :         }
     958             :     }
     959             :     else
     960           0 :         SetError( SVSTREAM_ACCESS_DENIED );
     961           0 : }
     962             : 
     963           0 : void Storage::SetConvertClass( const SvGlobalName & rConvertClass,
     964             :                                        sal_uLong nOriginalClipFormat,
     965             :                                        const String & rUserTypeName )
     966             : {
     967           0 :     if( Validate( sal_True ) )
     968             :     {
     969           0 :         SetClass( rConvertClass, nOriginalClipFormat, rUserTypeName );
     970             :         // plus the convert flag:
     971           0 :         StgOleStream aOle( *this, sal_True );
     972           0 :         aOle.GetFlags() |= 4;
     973           0 :         if( !aOle.Store() )
     974           0 :             SetError( aOle.GetError() );
     975             :     }
     976           0 : }
     977             : 
     978           6 : SvGlobalName Storage::GetClassName()
     979             : {
     980           6 :     StgCompObjStream aCompObj( *this, sal_False );
     981           6 :     if( aCompObj.Load() )
     982           6 :         return SvGlobalName( (const CLSID&) aCompObj.GetClsId() );
     983           0 :     pIo->ResetError();
     984             : 
     985           0 :     if ( pEntry )
     986           0 :         return SvGlobalName( (const CLSID&) pEntry->aEntry.GetClassId() );
     987             : 
     988           0 :     return SvGlobalName();
     989             : }
     990             : 
     991           8 : sal_uLong Storage::GetFormat()
     992             : {
     993           8 :     StgCompObjStream aCompObj( *this, sal_False );
     994           8 :     if( aCompObj.Load() )
     995           8 :         return aCompObj.GetCbFormat();
     996           0 :     pIo->ResetError();
     997           0 :     return 0;
     998             : }
     999             : 
    1000           0 : String Storage::GetUserName()
    1001             : {
    1002           0 :     StgCompObjStream aCompObj( *this, sal_False );
    1003           0 :     if( aCompObj.Load() )
    1004           0 :         return aCompObj.GetUserName();
    1005           0 :     pIo->ResetError();
    1006           0 :     return String();
    1007             : }
    1008             : 
    1009           0 : sal_Bool Storage::ShouldConvert()
    1010             : {
    1011           0 :     StgOleStream aOle( *this, sal_False );
    1012           0 :     if( aOle.Load() )
    1013           0 :         return sal_Bool( ( aOle.GetFlags() & 4 ) != 0 );
    1014             :     else
    1015             :     {
    1016           0 :         pIo->ResetError();
    1017           0 :         return sal_False;
    1018           0 :     }
    1019             : }
    1020             : 
    1021           4 : sal_Bool Storage::ValidateFAT()
    1022             : {
    1023           4 :     Link aLink = StgIo::GetErrorLink();
    1024           4 :     ErrCode nErr = pIo->ValidateFATs();
    1025           4 :     StgIo::SetErrorLink( aLink );
    1026           4 :     return nErr == ERRCODE_NONE;
    1027             : }
    1028             : 
    1029          14 : void Storage::SetDirty()
    1030             : {
    1031          14 :     if ( pEntry )
    1032          14 :         pEntry->SetDirty();
    1033          14 : }
    1034             : 
    1035          18 : void Storage::SetClassId( const ClsId& rId )
    1036             : {
    1037          18 :     if ( pEntry )
    1038          18 :         pEntry->aEntry.SetClassId( rId );
    1039          18 : }
    1040             : 
    1041          18 : const ClsId& Storage::GetClassId() const
    1042             : {
    1043          18 :     if ( pEntry )
    1044          18 :         return pEntry->aEntry.GetClassId();
    1045             : 
    1046             :     static ClsId aDummyId = {0,0,0,0,0,0,0,0,0,0,0};
    1047           0 :     return aDummyId;
    1048             : }
    1049             : 
    1050           0 : const SvStream* Storage::GetSvStream() const
    1051             : {
    1052           0 :     return GetSvStream_Impl();
    1053             : }
    1054             : 
    1055        2147 : sal_Bool Storage::Validate( sal_Bool bValidate ) const
    1056             : {
    1057        2147 :     sal_Bool bRet = Validate_Impl( bValidate );
    1058        2147 :     if ( !bRet )
    1059           2 :         SetError( SVSTREAM_ACCESS_DENIED );
    1060        2147 :     return bRet;
    1061             : }
    1062             : 
    1063         991 : sal_Bool Storage::ValidateMode( StreamMode nMode ) const
    1064             : {
    1065         991 :     sal_Bool bRet = ValidateMode_Impl( nMode );
    1066         991 :     if ( !bRet )
    1067           0 :         SetError( SVSTREAM_ACCESS_DENIED );
    1068         991 :     return bRet;
    1069             : }
    1070             : 
    1071         716 : sal_Bool Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
    1072             : {
    1073         716 :     sal_Bool bRet = ValidateMode_Impl( nMode, p );
    1074         716 :     if ( !bRet )
    1075           0 :         SetError( SVSTREAM_ACCESS_DENIED );
    1076         716 :     return bRet;
    1077             : }
    1078             : 
    1079          14 : sal_Bool Storage::Equals( const BaseStorage& rStorage ) const
    1080             : {
    1081          14 :     const Storage* pOther = PTR_CAST( Storage, &rStorage );
    1082          14 :     return pOther && ( pOther->pEntry == pEntry );
    1083             : }
    1084             : 
    1085             : 
    1086             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10