summaryrefslogtreecommitdiff
path: root/sfx2/source/doc/docfile.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/doc/docfile.cxx')
-rw-r--r--sfx2/source/doc/docfile.cxx3924
1 files changed, 3924 insertions, 0 deletions
diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
new file mode 100644
index 000000000000..6696b7670c63
--- /dev/null
+++ b/sfx2/source/doc/docfile.cxx
@@ -0,0 +1,3924 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sfx2.hxx"
+#include <sfx2/docfile.hxx>
+#include "sfx2/signaturestate.hxx"
+
+#include <uno/mapping.hxx>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/document/XDocumentRevisionListPersistence.hpp>
+#include <com/sun/star/document/LockedDocumentRequest.hpp>
+#include <com/sun/star/document/OwnLockOnDocumentRequest.hpp>
+#include <com/sun/star/document/LockedOnSavingRequest.hpp>
+#include <com/sun/star/document/LockFileIgnoreRequest.hpp>
+#include <com/sun/star/document/ChangedByOthersRequest.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/UseBackupException.hpp>
+#include <com/sun/star/embed/XOptimizedStorage.hpp>
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
+#include <com/sun/star/ucb/CommandFailedException.hpp>
+#include <com/sun/star/ucb/CommandAbortedException.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
+#include <com/sun/star/ucb/XContentProvider.hpp>
+#include <com/sun/star/ucb/XProgressHandler.hpp>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+#include <com/sun/star/util/XArchiver.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/io/XStreamListener.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/ucb/InsertCommandArgument.hpp>
+#include <com/sun/star/ucb/NameClash.hpp>
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/ucb/NameClashException.hpp>
+#include <com/sun/star/logging/XSimpleLogRing.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#ifndef _COM_SUN_STAR_SECURITY_DOCUMENTSIGNATURESINFORMATION_HPP_
+#include <com/sun/star/security/DocumentSignatureInformation.hpp>
+#endif
+#include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
+#include <tools/zcodec.hxx>
+#include <tools/cachestr.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/tempfile.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/componentcontext.hxx>
+#include <framework/interaction.hxx>
+#include <unotools/streamhelper.hxx>
+#include <unotools/localedatawrapper.hxx>
+#ifndef _MSGBOX_HXX //autogen
+#include <vcl/msgbox.hxx>
+#endif
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/lckbitem.hxx>
+#include <svtools/sfxecode.hxx>
+#include <svl/itemset.hxx>
+#include <svl/intitem.hxx>
+#include <svtools/svparser.hxx> // SvKeyValue
+#include <cppuhelper/weakref.hxx>
+#include <cppuhelper/implbase1.hxx>
+
+#define _SVSTDARR_ULONGS
+#define _SVSTDARR_STRINGSDTOR
+#include <svl/svstdarr.hxx>
+
+#include <unotools/streamwrap.hxx>
+
+#include <rtl/logfile.hxx>
+#include <osl/file.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::io;
+
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/mediadescriptor.hxx>
+#include <comphelper/configurationhelper.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/inetmime.hxx>
+#include <unotools/ucblockbytes.hxx>
+#include <unotools/pathoptions.hxx>
+#include <svtools/asynclink.hxx>
+#include <svl/inettype.hxx>
+#include <ucbhelper/contentbroker.hxx>
+#include <ucbhelper/commandenvironment.hxx>
+#include <unotools/localfilehelper.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/ucbhelper.hxx>
+#include <unotools/progresshandlerwrap.hxx>
+#include <ucbhelper/content.hxx>
+#include <ucbhelper/interactionrequest.hxx>
+#include <sot/stg.hxx>
+#include <unotools/saveopt.hxx>
+#include <svl/documentlockfile.hxx>
+
+#include "opostponedtruncationstream.hxx"
+#include "helper.hxx"
+#include <sfx2/request.hxx> // SFX_ITEMSET_SET
+#include <sfx2/app.hxx> // GetFilterMatcher
+#include <sfx2/frame.hxx> // LoadTargetFrame
+#include "fltfnc.hxx" // SfxFilterMatcher
+#include <sfx2/docfilt.hxx> // SfxFilter
+#include <sfx2/objsh.hxx> // CheckOpenMode
+#include <sfx2/docfac.hxx> // GetFilterContainer
+#include "doc.hrc"
+#include "openflag.hxx" // SFX_STREAM_READONLY etc.
+#include "sfxresid.hxx"
+#include <sfx2/appuno.hxx>
+
+//#include "xmlversion.hxx"
+
+#define MAX_REDIRECT 5
+
+
+sal_Bool IsReadonlyAccordingACL( const sal_Unicode* pFilePath );
+
+//==========================================================
+namespace {
+
+static const sal_Int8 LOCK_UI_NOLOCK = 0;
+static const sal_Int8 LOCK_UI_SUCCEEDED = 1;
+static const sal_Int8 LOCK_UI_TRY = 2;
+
+//----------------------------------------------------------------
+sal_Bool IsSystemFileLockingUsed()
+{
+ // check whether system file locking has been used, the default value is false
+ sal_Bool bUseSystemLock = sal_False;
+ try
+ {
+
+ uno::Reference< uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig(
+ ::comphelper::getProcessServiceFactory(),
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
+ ::comphelper::ConfigurationHelper::E_STANDARD );
+ if ( !xCommonConfig.is() )
+ throw uno::RuntimeException();
+
+ ::comphelper::ConfigurationHelper::readRelativeKey(
+ xCommonConfig,
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentSystemFileLocking" ) ) ) >>= bUseSystemLock;
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ return bUseSystemLock;
+}
+
+//----------------------------------------------------------------
+sal_Bool IsOOoLockFileUsed()
+{
+ // check whether system file locking has been used, the default value is false
+ sal_Bool bOOoLockFileUsed = sal_False;
+ try
+ {
+
+ uno::Reference< uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig(
+ ::comphelper::getProcessServiceFactory(),
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
+ ::comphelper::ConfigurationHelper::E_STANDARD );
+ if ( !xCommonConfig.is() )
+ throw uno::RuntimeException();
+
+ ::comphelper::ConfigurationHelper::readRelativeKey(
+ xCommonConfig,
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentOOoLockFile" ) ) ) >>= bOOoLockFileUsed;
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ return bOOoLockFileUsed;
+}
+
+} // anonymous namespace
+//==========================================================
+
+
+//----------------------------------------------------------------
+class SfxMediumHandler_Impl : public ::cppu::WeakImplHelper1< com::sun::star::task::XInteractionHandler >
+{
+ com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > m_xInter;
+
+public:
+ virtual void SAL_CALL handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& xRequest )
+ throw( com::sun::star::uno::RuntimeException );
+
+ SfxMediumHandler_Impl( com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > xInteraction )
+ : m_xInter( xInteraction )
+ {}
+
+ ~SfxMediumHandler_Impl();
+};
+
+//----------------------------------------------------------------
+SfxMediumHandler_Impl::~SfxMediumHandler_Impl()
+{
+}
+
+//----------------------------------------------------------------
+void SAL_CALL SfxMediumHandler_Impl::handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& xRequest )
+ throw( com::sun::star::uno::RuntimeException )
+{
+ if( !m_xInter.is() )
+ return;
+
+ com::sun::star::uno::Any aRequest = xRequest->getRequest();
+ com::sun::star::ucb::InteractiveIOException aIoException;
+ com::sun::star::ucb::UnsupportedDataSinkException aSinkException;
+ if ( (aRequest >>= aIoException) && ( aIoException.Code == IOErrorCode_ACCESS_DENIED || aIoException.Code == IOErrorCode_LOCKING_VIOLATION ) )
+ return;
+ else
+ if ( aRequest >>= aSinkException )
+ return;
+ else
+ m_xInter->handle( xRequest );
+}
+
+//----------------------------------------------------------------
+class SfxMedium_Impl : public SvCompatWeakBase
+{
+public:
+ ::ucbhelper::Content aContent;
+ sal_Bool bUpdatePickList : 1;
+ sal_Bool bIsTemp : 1;
+ sal_Bool bForceSynchron : 1;
+ sal_Bool bDownloadDone : 1;
+ sal_Bool bDontCallDoneLinkOnSharingError : 1;
+ sal_Bool bIsStorage: 1;
+ sal_Bool bUseInteractionHandler: 1;
+ sal_Bool bAllowDefaultIntHdl: 1;
+ sal_Bool bIsCharsetInitialized: 1;
+ sal_Bool bDisposeStorage: 1;
+ sal_Bool bStorageBasedOnInStream: 1;
+ sal_Bool m_bSalvageMode: 1;
+ sal_Bool m_bVersionsAlreadyLoaded: 1;
+ sal_Bool m_bLocked: 1;
+ sal_Bool m_bGotDateTime: 1;
+
+ uno::Reference < embed::XStorage > xStorage;
+
+ SfxMedium* pAntiImpl;
+
+ long nFileVersion;
+
+ const SfxFilter* pOrigFilter;
+ String aOrigURL;
+ String aPreRedirectionURL;
+ String aReferer;
+ DateTime aExpireTime;
+ SfxFrameWeak wLoadTargetFrame;
+ SvKeyValueIteratorRef xAttributes;
+
+ svtools::AsynchronLink aDoneLink;
+ svtools::AsynchronLink aAvailableLink;
+
+ uno::Sequence < util::RevisionTag > aVersions;
+
+ ::utl::TempFile* pTempFile;
+
+ uno::Reference < embed::XStorage > m_xZipStorage;
+ Reference < XInputStream > xInputStream;
+ Reference < XStream > xStream;
+
+ uno::Reference< io::XStream > m_xLockingStream;
+
+ sal_uInt32 nLastStorageError;
+ ::rtl::OUString aCharset;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xInteraction;
+
+ sal_Bool m_bRemoveBackup;
+ ::rtl::OUString m_aBackupURL;
+
+ // the following member is changed and makes sence only during saving
+ // TODO/LATER: in future the signature state should be controlled by the medium not by the document
+ // in this case the member will hold this information
+ sal_uInt16 m_nSignatureState;
+
+ util::DateTime m_aDateTime;
+
+ uno::Reference< logging::XSimpleLogRing > m_xLogRing;
+
+ SfxMedium_Impl( SfxMedium* pAntiImplP );
+ ~SfxMedium_Impl();
+};
+
+void SfxMedium::DataAvailable_Impl()
+{
+ pImp->aAvailableLink.ClearPendingCall();
+ pImp->aAvailableLink.Call( NULL );
+}
+
+void SfxMedium::Cancel_Impl()
+{
+ SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+}
+
+//------------------------------------------------------------------
+SfxMedium_Impl::SfxMedium_Impl( SfxMedium* pAntiImplP )
+ : SvCompatWeakBase( pAntiImplP ),
+ bUpdatePickList(sal_True),
+ bIsTemp( sal_False ),
+ bForceSynchron( sal_False ),
+ bDownloadDone( sal_True ),
+ bDontCallDoneLinkOnSharingError( sal_False ),
+ bIsStorage( sal_False ),
+ bUseInteractionHandler( sal_True ),
+ bAllowDefaultIntHdl( sal_False ),
+ bIsCharsetInitialized( sal_False ),
+ bStorageBasedOnInStream( sal_False ),
+ m_bSalvageMode( sal_False ),
+ m_bVersionsAlreadyLoaded( sal_False ),
+ m_bLocked( sal_False ),
+ m_bGotDateTime( sal_False ),
+ pAntiImpl( pAntiImplP ),
+ nFileVersion( 0 ),
+ pOrigFilter( 0 ),
+ aExpireTime( Date() + 10, Time() ),
+ pTempFile( NULL ),
+ nLastStorageError( 0 ),
+ m_bRemoveBackup( sal_False ),
+ m_nSignatureState( SIGNATURESTATE_NOSIGNATURES )
+{
+ aDoneLink.CreateMutex();
+}
+
+//------------------------------------------------------------------
+SfxMedium_Impl::~SfxMedium_Impl()
+{
+
+ aDoneLink.ClearPendingCall();
+ aAvailableLink.ClearPendingCall();
+
+ if ( pTempFile )
+ delete pTempFile;
+}
+
+//================================================================
+
+#define IMPL_CTOR(rootVal,URLVal) \
+ eError( SVSTREAM_OK ), \
+ \
+ bDirect( sal_False ), \
+ bRoot( rootVal ), \
+ bSetFilter( sal_False ), \
+ bTriedStorage( sal_False ), \
+ \
+ nStorOpenMode( SFX_STREAM_READWRITE ), \
+ pURLObj( URLVal ), \
+ pInStream(0), \
+ pOutStream( 0 )
+
+//------------------------------------------------------------------
+void SfxMedium::ResetError()
+{
+ eError = SVSTREAM_OK;
+ if( pInStream )
+ pInStream->ResetError();
+ if( pOutStream )
+ pOutStream->ResetError();
+}
+
+//------------------------------------------------------------------
+sal_uInt32 SfxMedium::GetLastStorageCreationState()
+{
+ return pImp->nLastStorageError;
+}
+
+//------------------------------------------------------------------
+void SfxMedium::AddLog( const ::rtl::OUString& aMessage )
+{
+ if ( !pImp->m_xLogRing.is() )
+ {
+ try
+ {
+ ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
+ if ( aContext.is() )
+ pImp->m_xLogRing.set( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), UNO_QUERY_THROW );
+ }
+ catch( uno::Exception& )
+ {}
+ }
+
+ if ( pImp->m_xLogRing.is() )
+ pImp->m_xLogRing->logString( aMessage );
+}
+
+//------------------------------------------------------------------
+void SfxMedium::SetError( sal_uInt32 nError, const ::rtl::OUString& aLogMessage )
+{
+ eError = nError;
+ if ( eError != ERRCODE_NONE && aLogMessage.getLength() )
+ AddLog( aLogMessage );
+}
+
+//------------------------------------------------------------------
+sal_uInt32 SfxMedium::GetErrorCode() const
+{
+ sal_uInt32 lError=eError;
+ if(!lError && pInStream)
+ lError=pInStream->GetErrorCode();
+ if(!lError && pOutStream)
+ lError=pOutStream->GetErrorCode();
+ return lError;
+}
+
+//------------------------------------------------------------------
+void SfxMedium::CheckFileDate( const util::DateTime& aInitDate )
+{
+ GetInitFileDate( sal_True );
+ if ( pImp->m_aDateTime.Seconds != aInitDate.Seconds
+ || pImp->m_aDateTime.Minutes != aInitDate.Minutes
+ || pImp->m_aDateTime.Hours != aInitDate.Hours
+ || pImp->m_aDateTime.Day != aInitDate.Day
+ || pImp->m_aDateTime.Month != aInitDate.Month
+ || pImp->m_aDateTime.Year != aInitDate.Year )
+ {
+ uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
+
+ if ( xHandler.is() )
+ {
+ try
+ {
+ ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
+ document::ChangedByOthersRequest() ) );
+ uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
+ aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
+ aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
+ xInteractionRequestImpl->setContinuations( aContinuations );
+
+ xHandler->handle( xInteractionRequestImpl.get() );
+
+ ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
+ if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
+ {
+ SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+ }
+ catch ( uno::Exception& )
+ {}
+ }
+ }
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::DocNeedsFileDateCheck()
+{
+ return ( !IsReadOnly() && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
+}
+
+//------------------------------------------------------------------
+util::DateTime SfxMedium::GetInitFileDate( sal_Bool bIgnoreOldValue )
+{
+ if ( ( bIgnoreOldValue || !pImp->m_bGotDateTime ) && aLogicName.Len() )
+ {
+ try
+ {
+ uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
+ ::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv );
+
+ aContent.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "DateModified" )) ) >>= pImp->m_aDateTime;
+ pImp->m_bGotDateTime = sal_True;
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+
+ return pImp->m_aDateTime;
+}
+
+//------------------------------------------------------------------
+Reference < XContent > SfxMedium::GetContent() const
+{
+ if ( !pImp->aContent.get().is() )
+ {
+ Reference < ::com::sun::star::ucb::XContent > xContent;
+ Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
+
+ SFX_ITEMSET_ARG( pSet, pItem, SfxUnoAnyItem, SID_CONTENT, sal_False);
+ if ( pItem )
+ pItem->GetValue() >>= xContent;
+
+ if ( xContent.is() )
+ {
+ try
+ {
+ pImp->aContent = ::ucbhelper::Content( xContent, xEnv );
+ }
+ catch ( Exception& )
+ {
+ }
+ }
+ else
+ {
+ // TODO: DBG_ERROR("SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
+ String aURL;
+ if ( aName.Len() )
+ ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL );
+ else if ( aLogicName.Len() )
+ aURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
+ if ( aURL.Len() )
+ ::ucbhelper::Content::create( aURL, xEnv, pImp->aContent );
+ }
+ }
+
+ return pImp->aContent.get();
+}
+
+//------------------------------------------------------------------
+::rtl::OUString SfxMedium::GetBaseURL( bool bForSaving )
+{
+ ::rtl::OUString aBaseURL;
+ const SfxStringItem* pBaseURLItem = static_cast<const SfxStringItem*>( GetItemSet()->GetItem(SID_DOC_BASEURL) );
+ if ( pBaseURLItem )
+ aBaseURL = pBaseURLItem->GetValue();
+ else if ( GetContent().is() )
+ {
+ try
+ {
+ Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI" )) );
+ aAny >>= aBaseURL;
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ }
+
+ if ( !aBaseURL.getLength() )
+ aBaseURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
+ }
+
+ if ( bForSaving )
+ {
+ SvtSaveOptions aOpt;
+ sal_Bool bIsRemote = IsRemote();
+ if( (bIsRemote && !aOpt.IsSaveRelINet()) || (!bRemote && !aOpt.IsSaveRelFSys()) )
+ return ::rtl::OUString();
+ }
+
+ return aBaseURL;
+}
+
+//------------------------------------------------------------------
+SvStream* SfxMedium::GetInStream()
+{
+ if ( pInStream )
+ return pInStream;
+
+ if ( pImp->pTempFile )
+ {
+ pInStream = new SvFileStream( aName, nStorOpenMode );
+
+ eError = pInStream->GetError();
+
+ if( !eError && (nStorOpenMode & STREAM_WRITE)
+ && ! pInStream->IsWritable() )
+ {
+ eError = ERRCODE_IO_ACCESSDENIED;
+ delete pInStream;
+ pInStream = NULL;
+ }
+ else
+ return pInStream;
+ }
+
+ GetMedium_Impl();
+
+ if ( GetError() )
+ return NULL;
+
+ return pInStream;
+}
+
+//------------------------------------------------------------------
+void SfxMedium::CloseInStream()
+{
+ CloseInStream_Impl();
+}
+
+void SfxMedium::CloseInStream_Impl()
+{
+ // if there is a storage based on the InStream, we have to
+ // close the storage, too, because otherwise the storage
+ // would use an invalid ( deleted ) stream.
+ if ( pInStream && pImp->xStorage.is() )
+ {
+ if ( pImp->bStorageBasedOnInStream )
+ CloseStorage();
+ }
+
+ if ( pInStream && !GetContent().is() )
+ {
+ CreateTempFile( sal_True );
+ return;
+ }
+
+ DELETEZ( pInStream );
+ if ( pSet )
+ pSet->ClearItem( SID_INPUTSTREAM );
+
+ CloseZipStorage_Impl();
+ pImp->xInputStream = uno::Reference< io::XInputStream >();
+
+ if ( !pOutStream )
+ {
+ // output part of the stream is not used so the whole stream can be closed
+ // TODO/LATER: is it correct?
+ pImp->xStream = uno::Reference< io::XStream >();
+ if ( pSet )
+ pSet->ClearItem( SID_STREAM );
+ }
+}
+
+//------------------------------------------------------------------
+SvStream* SfxMedium::GetOutStream()
+{
+ if ( !pOutStream )
+ {
+ // Create a temp. file if there is none because we always
+ // need one.
+ CreateTempFile( sal_False );
+
+ if ( pImp->pTempFile )
+ {
+ pOutStream = new SvFileStream( aName, STREAM_STD_READWRITE );
+ CloseStorage();
+ }
+ }
+
+ return pOutStream;
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::CloseOutStream()
+{
+ CloseOutStream_Impl();
+ return sal_True;
+}
+
+sal_Bool SfxMedium::CloseOutStream_Impl()
+{
+ if ( pOutStream )
+ {
+ // if there is a storage based on the OutStream, we have to
+ // close the storage, too, because otherwise the storage
+ // would use an invalid ( deleted ) stream.
+ //TODO/MBA: how to deal with this?!
+ //maybe we need a new flag when the storage was created from the outstream
+ if ( pImp->xStorage.is() )
+ {
+ //const SvStream *pStorage = aStorage->GetSvStream();
+ //if ( pStorage == pOutStream )
+ CloseStorage();
+ }
+
+ delete pOutStream;
+ pOutStream = NULL;
+ }
+
+ if ( !pInStream )
+ {
+ // input part of the stream is not used so the whole stream can be closed
+ // TODO/LATER: is it correct?
+ pImp->xStream = uno::Reference< io::XStream >();
+ if ( pSet )
+ pSet->ClearItem( SID_STREAM );
+ }
+
+ return sal_True;
+}
+
+//------------------------------------------------------------------
+const String& SfxMedium::GetPhysicalName() const
+{
+ if ( !aName.Len() && aLogicName.Len() )
+ (( SfxMedium*)this)->CreateFileStream();
+
+ // return the name then
+ return aName;
+}
+
+//------------------------------------------------------------------
+void SfxMedium::CreateFileStream()
+{
+ ForceSynchronStream_Impl( TRUE );
+ GetInStream();
+ if( pInStream )
+ {
+ CreateTempFile( sal_False );
+ pImp->bIsTemp = sal_True;
+ CloseInStream_Impl();
+ }
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::Commit()
+{
+ if( pImp->xStorage.is() )
+ StorageCommit_Impl();
+ else if( pOutStream )
+ pOutStream->Flush();
+ else if( pInStream )
+ pInStream->Flush();
+
+ if ( GetError() == SVSTREAM_OK )
+ {
+ // does something only in case there is a temporary file ( means aName points to different location than aLogicName )
+ Transfer_Impl();
+ }
+
+ sal_Bool bResult = ( GetError() == SVSTREAM_OK );
+
+ if ( bResult && DocNeedsFileDateCheck() )
+ GetInitFileDate( sal_True );
+
+ // remove truncation mode from the flags
+ nStorOpenMode &= (~STREAM_TRUNC);
+ return bResult;
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::IsStorage()
+{
+ if ( pImp->xStorage.is() )
+ return TRUE;
+
+ if ( bTriedStorage )
+ return pImp->bIsStorage;
+
+ if ( pImp->pTempFile )
+ {
+ String aURL;
+ if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL ) )
+ {
+ DBG_ERROR("Physical name not convertable!");
+ }
+ pImp->bIsStorage = SotStorage::IsStorageFile( aURL ) && !SotStorage::IsOLEStorage( aURL);
+ if ( !pImp->bIsStorage )
+ bTriedStorage = TRUE;
+ }
+ else if ( GetInStream() )
+ {
+ pImp->bIsStorage = SotStorage::IsStorageFile( pInStream ) && !SotStorage::IsOLEStorage( pInStream );
+ if ( !pInStream->GetError() && !pImp->bIsStorage )
+ bTriedStorage = TRUE;
+ }
+
+ return pImp->bIsStorage;
+}
+
+//------------------------------------------------------------------
+Link SfxMedium::GetDataAvailableLink() const
+{
+ return pImp->aAvailableLink.GetLink();
+}
+
+//------------------------------------------------------------------
+Link SfxMedium::GetDoneLink() const
+{
+ return pImp->aDoneLink.GetLink();
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::IsPreview_Impl()
+{
+ sal_Bool bPreview = sal_False;
+ SFX_ITEMSET_ARG( GetItemSet(), pPreview, SfxBoolItem, SID_PREVIEW, sal_False);
+ if ( pPreview )
+ bPreview = pPreview->GetValue();
+ else
+ {
+ SFX_ITEMSET_ARG( GetItemSet(), pFlags, SfxStringItem, SID_OPTIONS, sal_False);
+ if ( pFlags )
+ {
+ String aFileFlags = pFlags->GetValue();
+ aFileFlags.ToUpperAscii();
+ if ( STRING_NOTFOUND != aFileFlags.Search( 'B' ) )
+ bPreview = sal_True;
+ }
+ }
+
+ return bPreview;
+}
+
+//------------------------------------------------------------------
+void SfxMedium::StorageBackup_Impl()
+{
+ ::ucbhelper::Content aOriginalContent;
+ Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
+
+ sal_Bool bBasedOnOriginalFile = ( !pImp->pTempFile && !( aLogicName.Len() && pImp->m_bSalvageMode )
+ && GetURLObject().GetMainURL( INetURLObject::NO_DECODE ).getLength()
+ && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
+ && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
+
+ if ( bBasedOnOriginalFile && !pImp->m_aBackupURL.getLength()
+ && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aOriginalContent ) )
+ {
+ DoInternalBackup_Impl( aOriginalContent );
+ if( !pImp->m_aBackupURL.getLength() )
+ SetError( ERRCODE_SFX_CANTCREATEBACKUP, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+}
+
+//------------------------------------------------------------------
+::rtl::OUString SfxMedium::GetBackup_Impl()
+{
+ if ( !pImp->m_aBackupURL.getLength() )
+ StorageBackup_Impl();
+
+ return pImp->m_aBackupURL;
+}
+
+//------------------------------------------------------------------
+uno::Reference < embed::XStorage > SfxMedium::GetOutputStorage()
+{
+ if ( GetError() )
+ return uno::Reference< embed::XStorage >();
+
+ // if the medium was constructed with a Storage: use this one, not a temp. storage
+ // if a temporary storage already exists: use it
+ if ( pImp->xStorage.is() && ( !aLogicName.Len() || pImp->pTempFile ) )
+ return pImp->xStorage;
+
+ // if necessary close stream that was used for reading
+ if ( pInStream && !pInStream->IsWritable() )
+ CloseInStream();
+
+ DBG_ASSERT( !pOutStream, "OutStream in a readonly Medium?!" );
+
+ // TODO/LATER: The current solution is to store the document temporary and then copy it to the target location;
+ // in future it should be stored directly and then copied to the temporary location, since in this case no
+ // file attributes have to be preserved and system copying mechanics could be used instead of streaming.
+ CreateTempFileNoCopy();
+
+ return GetStorage();
+}
+
+//------------------------------------------------------------------
+void SfxMedium::SetPasswordToStorage_Impl()
+{
+ // in case media-descriptor contains password it should be used on opening
+ if ( pImp->xStorage.is() && pSet )
+ {
+ ::rtl::OUString aPasswd;
+ if ( GetPasswd_Impl( pSet, aPasswd ) )
+ {
+ try
+ {
+ ::comphelper::OStorageHelper::SetCommonStoragePassword( pImp->xStorage, aPasswd );
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( sal_False, "It must be possible to set a common password for the storage" );
+ // TODO/LATER: set the error code in case of problem
+ // SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------
+sal_Int8 SfxMedium::ShowLockedDocumentDialog( const uno::Sequence< ::rtl::OUString >& aData, sal_Bool bIsLoading, sal_Bool bOwnLock )
+{
+ sal_Int8 nResult = LOCK_UI_NOLOCK;
+
+ // show the interaction regarding the document opening
+ uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
+
+ if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler.is() && ( bIsLoading || bOwnLock ) )
+ {
+ ::rtl::OUString aDocumentURL = GetURLObject().GetLastName();
+ ::rtl::OUString aInfo;
+ ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl;
+
+ if ( bOwnLock )
+ {
+ if ( aData.getLength() > LOCKFILE_EDITTIME_ID )
+ aInfo = aData[LOCKFILE_EDITTIME_ID];
+
+ xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
+ document::OwnLockOnDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo, !bIsLoading ) ) );
+ }
+ else
+ {
+ if ( aData.getLength() > LOCKFILE_EDITTIME_ID )
+ {
+ if ( aData[LOCKFILE_OOOUSERNAME_ID].getLength() )
+ aInfo = aData[LOCKFILE_OOOUSERNAME_ID];
+ else
+ aInfo = aData[LOCKFILE_SYSUSERNAME_ID];
+
+ if ( aInfo.getLength() && aData[LOCKFILE_EDITTIME_ID].getLength() )
+ {
+ aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " ( " ) );
+ aInfo += aData[LOCKFILE_EDITTIME_ID];
+ aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " )" ) );
+ }
+ }
+
+ if ( bIsLoading )
+ {
+ xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
+ document::LockedDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
+ }
+ else
+ {
+ xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
+ document::LockedOnSavingRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
+
+ }
+ }
+
+ uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
+ aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
+ aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
+ aContinuations[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl.get() );
+ xInteractionRequestImpl->setContinuations( aContinuations );
+
+ xHandler->handle( xInteractionRequestImpl.get() );
+
+ ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
+ if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
+ {
+ SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+ else if ( uno::Reference< task::XInteractionDisapprove >( xSelected.get(), uno::UNO_QUERY ).is() )
+ {
+ // own lock on loading, user has selected to ignore the lock
+ // own lock on saving, user has selected to ignore the lock
+ // alien lock on loading, user has selected to edit a copy of document
+ // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
+ if ( bIsLoading && !bOwnLock )
+ {
+ // means that a copy of the document should be opened
+ GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE, sal_True ) );
+ }
+ else if ( bOwnLock )
+ nResult = LOCK_UI_SUCCEEDED;
+ }
+ else // if ( XSelected == aContinuations[1] )
+ {
+ // own lock on loading, user has selected to open readonly
+ // own lock on saving, user has selected to open readonly
+ // alien lock on loading, user has selected to retry saving
+ // TODO/LATER: alien lock on saving, user has selected to retry saving
+
+ if ( bIsLoading )
+ GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
+ else
+ nResult = LOCK_UI_TRY;
+ }
+ }
+ else
+ {
+ if ( bIsLoading )
+ {
+ // if no interaction handler is provided the default answer is open readonly
+ // that usually happens in case the document is loaded per API
+ // so the document must be opened readonly for backward compatibility
+ GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
+ }
+ else
+ SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+
+ }
+
+ return nResult;
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::LockOrigFileOnDemand( sal_Bool bLoading, sal_Bool bNoUI )
+{
+ // returns true if the document can be opened for editing ( even if it should be a copy )
+ // otherwise the document should be opened readonly
+ // if user cancel the loading the ERROR_ABORT is set
+
+ if ( pImp->m_bLocked && bLoading && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
+ {
+ // if the document is already locked the system locking might be temporarely off after storing
+ // check whether the system file locking should be taken again
+ GetLockingStream_Impl();
+ }
+
+ sal_Bool bResult = pImp->m_bLocked;
+
+ if ( !bResult )
+ {
+ // no read-write access is necessary on loading if the document is explicitly opened as copy
+ SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem, SfxBoolItem, SID_TEMPLATE, sal_False);
+ bResult = ( bLoading && pTemplateItem && pTemplateItem->GetValue() );
+ }
+
+ if ( !bResult && !IsReadOnly() )
+ {
+ sal_Bool bContentReadonly = sal_False;
+ if ( bLoading && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
+ {
+ // let the original document be opened to check the possibility to open it for editing
+ // and to let the writable stream stay open to hold the lock on the document
+ GetLockingStream_Impl();
+ }
+
+ // "IsReadOnly" property does not allow to detect whether the file is readonly always
+ // so we try always to open the file for editing
+ // the file is readonly only in case the read-write stream can not be opened
+ if ( bLoading && !pImp->m_xLockingStream.is() )
+ {
+ try
+ {
+ // MediaDescriptor does this check also, the duplication should be avoided in future
+ Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
+ ::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv );
+ aContent.getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) ) >>= bContentReadonly;
+ }
+ catch( uno::Exception )
+ {}
+
+ if ( !bContentReadonly )
+ {
+ // the file is not readonly, check the ACL
+
+ String aPhysPath;
+ if ( ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aPhysPath ) )
+ bContentReadonly = IsReadonlyAccordingACL( aPhysPath.GetBuffer() );
+ }
+ }
+
+ // do further checks only if the file not readonly in fs
+ if ( !bContentReadonly )
+ {
+ // the special file locking should be used only for file URLs
+ if ( ::utl::LocalFileHelper::IsLocalFile( aLogicName ) )
+ {
+
+ // in case of storing the document should request the output before locking
+ if ( bLoading )
+ {
+ // let the stream be opened to check the system file locking
+ GetMedium_Impl();
+ }
+
+ sal_Int8 bUIStatus = LOCK_UI_NOLOCK;
+
+ // check whether system file locking has been used, the default value is false
+ sal_Bool bUseSystemLock = IsSystemFileLockingUsed();
+
+ // TODO/LATER: This implementation does not allow to detect the system lock on saving here, actually this is no big problem
+ // if system lock is used the writeable stream should be available
+ sal_Bool bHandleSysLocked = ( bLoading && bUseSystemLock && !pImp->xStream.is() && !pOutStream );
+
+ do
+ {
+ try
+ {
+ ::svt::DocumentLockFile aLockFile( aLogicName );
+ if ( !bHandleSysLocked )
+ {
+ try
+ {
+ bResult = aLockFile.CreateOwnLockFile();
+ }
+ catch ( ucb::InteractiveIOException& e )
+ {
+ // exception means that the lock file can not be successfuly accessed
+ // in this case it should be ignored if system file locking is anyway active
+ if ( bUseSystemLock || !IsOOoLockFileUsed() )
+ {
+ bResult = sal_True;
+ // take the ownership over the lock file
+ aLockFile.OverwriteOwnLockFile();
+ }
+ else if ( e.Code == IOErrorCode_INVALID_PARAMETER )
+ {
+ // system file locking is not active, ask user whether he wants to open the document without any locking
+ uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
+
+ if ( xHandler.is() )
+ {
+ ::rtl::Reference< ::ucbhelper::InteractionRequest > xIgnoreRequestImpl
+ = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
+
+ uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 2 );
+ aContinuations[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl.get() );
+ aContinuations[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl.get() );
+ xIgnoreRequestImpl->setContinuations( aContinuations );
+
+ xHandler->handle( xIgnoreRequestImpl.get() );
+
+ ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xIgnoreRequestImpl->getSelection();
+ bResult = ( uno::Reference< task::XInteractionApprove >( xSelected.get(), uno::UNO_QUERY ).is() );
+ }
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ // exception means that the lock file can not be successfuly accessed
+ // in this case it should be ignored if system file locking is anyway active
+ if ( bUseSystemLock || !IsOOoLockFileUsed() )
+ {
+ bResult = sal_True;
+ // take the ownership over the lock file
+ aLockFile.OverwriteOwnLockFile();
+ }
+ }
+
+ // in case OOo locking is turned off the lock file is still written if possible
+ // but it is ignored while deciding whether the document should be opened for editing or not
+ if ( !bResult && !IsOOoLockFileUsed() )
+ {
+ bResult = sal_True;
+ // take the ownership over the lock file
+ aLockFile.OverwriteOwnLockFile();
+ }
+ }
+
+
+ if ( !bResult )
+ {
+ uno::Sequence< ::rtl::OUString > aData;
+ try
+ {
+ // impossibility to get data is no real problem
+ aData = aLockFile.GetLockData();
+ }
+ catch( uno::Exception ) {}
+
+ sal_Bool bOwnLock = sal_False;
+
+ if ( !bHandleSysLocked )
+ {
+ uno::Sequence< ::rtl::OUString > aOwnData = aLockFile.GenerateOwnEntry();
+ bOwnLock = ( aData.getLength() > LOCKFILE_USERURL_ID
+ && aOwnData.getLength() > LOCKFILE_USERURL_ID
+ && aOwnData[LOCKFILE_SYSUSERNAME_ID].equals( aData[LOCKFILE_SYSUSERNAME_ID] ) );
+
+ if ( bOwnLock
+ && aOwnData[LOCKFILE_LOCALHOST_ID].equals( aData[LOCKFILE_LOCALHOST_ID] )
+ && aOwnData[LOCKFILE_USERURL_ID].equals( aData[LOCKFILE_USERURL_ID] ) )
+ {
+ // this is own lock from the same installation, it could remain because of crash
+ bResult = sal_True;
+ }
+ }
+
+ if ( !bResult && !bNoUI )
+ {
+ bUIStatus = ShowLockedDocumentDialog( aData, bLoading, bOwnLock );
+ if ( bUIStatus == LOCK_UI_SUCCEEDED )
+ {
+ // take the ownership over the lock file
+ bResult = aLockFile.OverwriteOwnLockFile();
+ }
+ }
+
+ bHandleSysLocked = sal_False;
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+ } while( !bResult && bUIStatus == LOCK_UI_TRY );
+
+ pImp->m_bLocked = bResult;
+ }
+ else
+ {
+ // this is no file URL, check whether the file is readonly
+ bResult = !bContentReadonly;
+ }
+ }
+ }
+
+ if ( !bResult && GetError() == ERRCODE_NONE )
+ {
+ // the error should be set in case it is storing process
+ // or the document has been opened for editing explicitly
+
+ SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, FALSE );
+ if ( !bLoading || (pReadOnlyItem && !pReadOnlyItem->GetValue()) )
+ SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ else
+ GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
+ }
+
+ // when the file is locked, get the current file date
+ if ( bResult && DocNeedsFileDateCheck() )
+ GetInitFileDate( sal_True );
+
+ return bResult;
+}
+
+//------------------------------------------------------------------
+uno::Reference < embed::XStorage > SfxMedium::GetStorage( sal_Bool bCreateTempIfNo )
+{
+ if ( pImp->xStorage.is() || bTriedStorage )
+ return pImp->xStorage;
+
+ uno::Sequence< uno::Any > aArgs( 2 );
+
+ // the medium should be retrieved before temporary file creation
+ // to let the MediaDescriptor be filled with the streams
+ GetMedium_Impl();
+
+ if ( bCreateTempIfNo )
+ CreateTempFile( sal_False );
+
+ GetMedium_Impl();
+
+ if ( GetError() )
+ return pImp->xStorage;
+
+ SFX_ITEMSET_ARG( GetItemSet(), pRepairItem, SfxBoolItem, SID_REPAIRPACKAGE, sal_False);
+ if ( pRepairItem && pRepairItem->GetValue() )
+ {
+ // the storage should be created for repairing mode
+ CreateTempFile( sal_False );
+ GetMedium_Impl();
+
+ Reference< ::com::sun::star::ucb::XProgressHandler > xProgressHandler;
+ Reference< ::com::sun::star::task::XStatusIndicator > xStatusIndicator;
+
+ SFX_ITEMSET_ARG( GetItemSet(), pxProgressItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, sal_False );
+ if( pxProgressItem && ( pxProgressItem->GetValue() >>= xStatusIndicator ) )
+ xProgressHandler = Reference< ::com::sun::star::ucb::XProgressHandler >(
+ new utl::ProgressHandlerWrap( xStatusIndicator ) );
+
+ uno::Sequence< beans::PropertyValue > aAddProps( 2 );
+ aAddProps[0].Name = ::rtl::OUString::createFromAscii( "RepairPackage" );
+ aAddProps[0].Value <<= (sal_Bool)sal_True;
+ aAddProps[1].Name = ::rtl::OUString::createFromAscii( "StatusIndicator" );
+ aAddProps[1].Value <<= xProgressHandler;
+
+ // the first arguments will be filled later
+ aArgs.realloc( 3 );
+ aArgs[2] <<= aAddProps;
+ }
+
+ if ( pImp->xStream.is() )
+ {
+ // since the storage is based on temporary stream we open it always read-write
+ aArgs[0] <<= pImp->xStream;
+ aArgs[1] <<= embed::ElementModes::READWRITE;
+ pImp->bStorageBasedOnInStream = sal_True;
+ }
+ else if ( pImp->xInputStream.is() )
+ {
+ // since the storage is based on temporary stream we open it always read-write
+ aArgs[0] <<= pImp->xInputStream;
+ aArgs[1] <<= embed::ElementModes::READ;
+ pImp->bStorageBasedOnInStream = sal_True;
+ }
+ else
+ {
+ CloseStreams_Impl();
+ aArgs[0] <<= ::rtl::OUString( aName );
+ aArgs[1] <<= embed::ElementModes::READ;
+ pImp->bStorageBasedOnInStream = sal_False;
+ }
+
+ try
+ {
+ pImp->xStorage = uno::Reference< embed::XStorage >(
+ ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs ),
+ uno::UNO_QUERY );
+ }
+ catch( uno::Exception& )
+ {
+ // impossibility to create the storage is no error
+ }
+
+ if( ( pImp->nLastStorageError = GetError() ) != SVSTREAM_OK )
+ {
+ pImp->xStorage = 0;
+ if ( pInStream )
+ pInStream->Seek(0);
+ return uno::Reference< embed::XStorage >();
+ }
+
+ bTriedStorage = sal_True;
+
+ // TODO/LATER: Get versionlist on demand
+ if ( pImp->xStorage.is() )
+ {
+ SetPasswordToStorage_Impl();
+ GetVersionList();
+ }
+
+ SFX_ITEMSET_ARG( pSet, pVersion, SfxInt16Item, SID_VERSION, sal_False);
+
+ BOOL bResetStorage = FALSE;
+ if ( pVersion && pVersion->GetValue() )
+ {
+ // Alle verf"ugbaren Versionen einlesen
+ if ( pImp->aVersions.getLength() )
+ {
+ // Die zum Kommentar passende Version suchen
+ // Die Versionen sind von 1 an durchnumeriert, mit negativen
+ // Versionsnummern werden die Versionen von der aktuellen aus
+ // r"uckw"arts gez"ahlt
+ short nVersion = pVersion ? pVersion->GetValue() : 0;
+ if ( nVersion<0 )
+ nVersion = ( (short) pImp->aVersions.getLength() ) + nVersion;
+ else if ( nVersion )
+ nVersion--;
+
+ util::RevisionTag& rTag = pImp->aVersions[nVersion];
+ {
+ // SubStorage f"ur alle Versionen "offnen
+ uno::Reference < embed::XStorage > xSub = pImp->xStorage->openStorageElement( DEFINE_CONST_UNICODE( "Versions" ),
+ embed::ElementModes::READ );
+
+ DBG_ASSERT( xSub.is(), "Versionsliste, aber keine Versionen!" );
+
+ // Dort ist die Version als gepackter Stream gespeichert
+ uno::Reference < io::XStream > xStr = xSub->openStreamElement( rTag.Identifier, embed::ElementModes::READ );
+ SvStream* pStream = utl::UcbStreamHelper::CreateStream( xStr );
+ if ( pStream && pStream->GetError() == SVSTREAM_OK )
+ {
+ // Stream ins TempDir auspacken
+ ::utl::TempFile aTempFile;
+ String aTmpName = aTempFile.GetURL();
+ SvFileStream aTmpStream( aTmpName, SFX_STREAM_READWRITE );
+
+ *pStream >> aTmpStream;
+ aTmpStream.Close();
+
+ // Datei als Storage "offnen
+ nStorOpenMode = SFX_STREAM_READONLY;
+ pImp->xStorage = comphelper::OStorageHelper::GetStorageFromURL( aTmpName, embed::ElementModes::READ );
+ pImp->bStorageBasedOnInStream = sal_False;
+ String aTemp;
+ ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName, aTemp );
+ SetPhysicalName_Impl( aTemp );
+
+ pImp->bIsTemp = sal_True;
+ GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
+ // TODO/MBA
+ pImp->aVersions.realloc(0);
+ }
+ else
+ bResetStorage = TRUE;
+ }
+ }
+ else
+ bResetStorage = TRUE;
+ }
+
+ if ( bResetStorage )
+ {
+ pImp->xStorage = 0;
+ if ( pInStream )
+ pInStream->Seek( 0L );
+ }
+
+ pImp->bIsStorage = pImp->xStorage.is();
+ return pImp->xStorage;
+}
+
+//------------------------------------------------------------------
+uno::Reference< embed::XStorage > SfxMedium::GetZipStorageToSign_Impl( sal_Bool bReadOnly )
+{
+ if ( !GetError() && !pImp->m_xZipStorage.is() )
+ {
+ // very careful!!!
+ // if bReadOnly == sal_False and there is no temporary file the original file might be used
+ GetMedium_Impl();
+
+ try
+ {
+ // we can not sign document if there is no stream
+ // should it be possible at all?
+ if ( !bReadOnly && pImp->xStream.is() )
+ {
+ pImp->m_xZipStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING, pImp->xStream, embed::ElementModes::READWRITE );
+ }
+ else if ( pImp->xInputStream.is() )
+ {
+ pImp->m_xZipStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( ZIP_STORAGE_FORMAT_STRING, pImp->xInputStream );
+ }
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( sal_False, "No possibility to get readonly version of storage from medium!\n" );
+ }
+
+ if ( GetError() ) // do not remove warnings
+ ResetError();
+ }
+
+ return pImp->m_xZipStorage;
+}
+
+//------------------------------------------------------------------
+void SfxMedium::CloseZipStorage_Impl()
+{
+ if ( pImp->m_xZipStorage.is() )
+ {
+ try {
+ pImp->m_xZipStorage->dispose();
+ } catch( uno::Exception& )
+ {}
+
+ pImp->m_xZipStorage = uno::Reference< embed::XStorage >();
+ }
+}
+
+//------------------------------------------------------------------
+void SfxMedium::CloseStorage()
+{
+ if ( pImp->xStorage.is() )
+ {
+ uno::Reference < lang::XComponent > xComp( pImp->xStorage, uno::UNO_QUERY );
+ // in the salvage mode the medium does not own the storage
+ if ( pImp->bDisposeStorage && !pImp->m_bSalvageMode )
+ {
+ try {
+ xComp->dispose();
+ } catch( uno::Exception& )
+ {
+ OSL_ENSURE( sal_False, "Medium's storage is already disposed!\n" );
+ }
+ }
+
+ pImp->xStorage = 0;
+ pImp->bStorageBasedOnInStream = sal_False;
+ }
+
+ bTriedStorage = sal_False;
+ pImp->bIsStorage = sal_False;
+}
+
+void SfxMedium::CanDisposeStorage_Impl( sal_Bool bDisposeStorage )
+{
+ pImp->bDisposeStorage = bDisposeStorage;
+}
+
+sal_Bool SfxMedium::WillDisposeStorageOnClose_Impl()
+{
+ return pImp->bDisposeStorage;
+}
+
+//------------------------------------------------------------------
+void SfxMedium::SetOpenMode( StreamMode nStorOpen,
+ sal_Bool bDirectP,
+ sal_Bool bDontClose )
+{
+ if ( nStorOpenMode != nStorOpen )
+ {
+ nStorOpenMode = nStorOpen;
+
+ if( !bDontClose )
+ {
+ if ( pImp->xStorage.is() )
+ CloseStorage();
+
+ CloseStreams_Impl();
+ }
+ }
+
+ bDirect = bDirectP;
+ bSetFilter = sal_False;
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::UseBackupToRestore_Impl( ::ucbhelper::Content& aOriginalContent,
+ const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
+{
+ try
+ {
+ ::ucbhelper::Content aTransactCont( pImp->m_aBackupURL, xComEnv );
+
+ Reference< XInputStream > aOrigInput = aTransactCont.openStream();
+ aOriginalContent.writeStream( aOrigInput, sal_True );
+ return sal_True;
+ }
+ catch( Exception& )
+ {
+ // in case of failure here the backup file should not be removed
+ // TODO/LATER: a message should be used to let user know about the backup
+ pImp->m_bRemoveBackup = sal_False;
+ // TODO/LATER: needs a specific error code
+ eError = ERRCODE_IO_GENERAL;
+ }
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::StorageCommit_Impl()
+{
+ sal_Bool bResult = sal_False;
+ Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
+ ::ucbhelper::Content aOriginalContent;
+
+ if ( pImp->xStorage.is() )
+ {
+ if ( !GetError() )
+ {
+ uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ {
+ try
+ {
+ xTrans->commit();
+ CloseZipStorage_Impl();
+ bResult = sal_True;
+ }
+ catch ( embed::UseBackupException& aBackupExc )
+ {
+ // since the temporary file is created always now, the scenario is close to be impossible
+ if ( !pImp->pTempFile )
+ {
+ OSL_ENSURE( pImp->m_aBackupURL.getLength(), "No backup on storage commit!\n" );
+ if ( pImp->m_aBackupURL.getLength()
+ && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
+ xDummyEnv,
+ aOriginalContent ) )
+ {
+ // use backup to restore the file
+ // the storage has already disconnected from original location
+ CloseAndReleaseStreams_Impl();
+ if ( !UseBackupToRestore_Impl( aOriginalContent, xDummyEnv ) )
+ {
+ // connect the medium to the temporary file of the storage
+ pImp->aContent = ::ucbhelper::Content();
+ aName = aBackupExc.TemporaryFileURL;
+ OSL_ENSURE( aName.Len(), "The exception _must_ contain the temporary URL!\n" );
+ }
+ }
+
+ if ( !GetError() )
+ SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ //TODO/LATER: improve error handling
+ SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+ }
+ }
+ }
+
+ return bResult;
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::TransactedTransferForFS_Impl( const INetURLObject& aSource,
+ const INetURLObject& aDest,
+ const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
+{
+ sal_Bool bResult = sal_False;
+ Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
+ Reference< XOutputStream > aDestStream;
+ ::ucbhelper::Content aOriginalContent;
+
+ try
+ {
+ aOriginalContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
+ }
+ catch ( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ eError = ERRCODE_ABORT;
+ }
+ catch ( ::com::sun::star::ucb::CommandFailedException& )
+ {
+ eError = ERRCODE_ABORT;
+ }
+ catch (const ::com::sun::star::ucb::ContentCreationException& ex)
+ {
+ eError = ERRCODE_IO_GENERAL;
+ if (
+ (ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER ) ||
+ (ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
+ )
+ {
+ eError = ERRCODE_IO_NOTEXISTSPATH;
+ }
+ }
+ catch (const ::com::sun::star::uno::Exception&)
+ {
+ eError = ERRCODE_IO_GENERAL;
+ }
+
+ if( !eError || (eError & ERRCODE_WARNING_MASK) )
+ {
+ if ( pImp->xStorage.is() )
+ CloseStorage();
+
+ CloseStreams_Impl();
+
+ ::ucbhelper::Content aTempCont;
+ if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aTempCont ) )
+ {
+ sal_Bool bTransactStarted = sal_False;
+ SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
+ SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
+ sal_Bool bRename = pRename ? pRename->GetValue() : FALSE;
+ sal_Bool bOverWrite = pOverWrite ? pOverWrite->GetValue() : !bRename;
+
+ try
+ {
+ if( bOverWrite && ::utl::UCBContentHelper::IsDocument( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) )
+ {
+ if( ! pImp->m_aBackupURL.getLength() )
+ DoInternalBackup_Impl( aOriginalContent );
+
+ if( pImp->m_aBackupURL.getLength() )
+ {
+ Reference< XInputStream > aTempInput = aTempCont.openStream();
+ bTransactStarted = sal_True;
+ aOriginalContent.setPropertyValue( ::rtl::OUString::createFromAscii( "Size" ),
+ uno::makeAny( (sal_Int64)0 ) );
+ aOriginalContent.writeStream( aTempInput, bOverWrite );
+ bResult = sal_True;
+ }
+ else
+ {
+ eError = ERRCODE_SFX_CANTCREATEBACKUP;
+ }
+ }
+ else
+ {
+ Reference< XInputStream > aTempInput = aTempCont.openStream();
+ aOriginalContent.writeStream( aTempInput, bOverWrite );
+ bResult = sal_True;
+ }
+ }
+ catch ( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ eError = ERRCODE_ABORT;
+ }
+ catch ( ::com::sun::star::ucb::CommandFailedException& )
+ {
+ eError = ERRCODE_ABORT;
+ }
+ catch ( ::com::sun::star::ucb::InteractiveIOException& r )
+ {
+ if ( r.Code == IOErrorCode_ACCESS_DENIED )
+ eError = ERRCODE_IO_ACCESSDENIED;
+ else if ( r.Code == IOErrorCode_NOT_EXISTING )
+ eError = ERRCODE_IO_NOTEXISTS;
+ else if ( r.Code == IOErrorCode_CANT_READ )
+ eError = ERRCODE_IO_CANTREAD;
+ else
+ eError = ERRCODE_IO_GENERAL;
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ eError = ERRCODE_IO_GENERAL;
+ }
+
+ if ( bResult )
+ {
+ if ( pImp->pTempFile )
+ {
+ pImp->pTempFile->EnableKillingFile( sal_True );
+ delete pImp->pTempFile;
+ pImp->pTempFile = NULL;
+ }
+ }
+ else if ( bTransactStarted )
+ {
+ UseBackupToRestore_Impl( aOriginalContent, xDummyEnv );
+ }
+ }
+ else
+ eError = ERRCODE_IO_CANTREAD;
+ }
+
+ return bResult;
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::TryDirectTransfer( const ::rtl::OUString& aURL, SfxItemSet& aTargetSet )
+{
+ if ( GetError() )
+ return sal_False;
+
+ // if the document had no password it should be stored without password
+ // if the document had password it should be stored with the same password
+ // otherwise the stream copying can not be done
+ SFX_ITEMSET_ARG( &aTargetSet, pNewPassItem, SfxStringItem, SID_PASSWORD, sal_False );
+ SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem, SfxStringItem, SID_PASSWORD, sal_False );
+ if ( ( !pNewPassItem && !pOldPassItem )
+ || ( pNewPassItem && pOldPassItem && pNewPassItem->GetValue().Equals( pOldPassItem->GetValue() ) ) )
+ {
+ // the filter must be the same
+ SFX_ITEMSET_ARG( &aTargetSet, pNewFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
+ SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
+ if ( pNewFilterItem && pOldFilterItem && pNewFilterItem->GetValue().Equals( pOldFilterItem->GetValue() ) )
+ {
+ // get the input stream and copy it
+ // in case of success return true
+ uno::Reference< io::XInputStream > xInStream = GetInputStream();
+
+ ResetError();
+ if ( xInStream.is() )
+ {
+ try
+ {
+ uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
+ sal_Int64 nPos = 0;
+ if ( xSeek.is() )
+ {
+ nPos = xSeek->getPosition();
+ xSeek->seek( 0 );
+ }
+
+ uno::Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
+ ::ucbhelper::Content aTargetContent( aURL, xEnv );
+
+ InsertCommandArgument aInsertArg;
+ aInsertArg.Data = xInStream;
+ SFX_ITEMSET_ARG( &aTargetSet, pRename, SfxBoolItem, SID_RENAME, sal_False );
+ SFX_ITEMSET_ARG( &aTargetSet, pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
+ if ( (pOverWrite && !pOverWrite->GetValue()) // argument says: never overwrite
+ || (pRename && pRename->GetValue()) ) // argument says: rename file
+ aInsertArg.ReplaceExisting = sal_False;
+ else
+ aInsertArg.ReplaceExisting = sal_True; // default is overwrite existing files
+
+ Any aCmdArg;
+ aCmdArg <<= aInsertArg;
+ aTargetContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
+ aCmdArg );
+
+ if ( xSeek.is() )
+ xSeek->seek( nPos );
+
+ return sal_True;
+ }
+ catch( uno::Exception& )
+ {}
+ }
+ }
+ }
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------
+void SfxMedium::Transfer_Impl()
+{
+ // The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
+ String aNameURL;
+ if ( pImp->pTempFile )
+ aNameURL = pImp->pTempFile->GetURL();
+ else if ( aLogicName.Len() && pImp->m_bSalvageMode )
+ {
+ // makes sence only in case logic name is set
+ if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aNameURL ) )
+ OSL_ENSURE( sal_False, "The medium name is not convertable!\n" );
+ }
+
+ if ( aNameURL.Len() && ( !eError || (eError & ERRCODE_WARNING_MASK) ) )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::Transfer_Impl, copying to target" );
+
+ Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
+ Reference< XOutputStream > rOutStream;
+
+ // in case an output stream is provided from outside and the URL is correct
+ // commit to the stream
+ if( aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL )
+ {
+ // TODO/LATER: support storing to SID_STREAM
+ SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
+ if( pOutStreamItem && ( pOutStreamItem->GetValue() >>= rOutStream ) )
+ {
+ if ( pImp->xStorage.is() )
+ CloseStorage();
+
+ CloseStreams_Impl();
+
+ INetURLObject aSource( aNameURL );
+ ::ucbhelper::Content aTempCont;
+ if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aTempCont ) )
+ {
+ try
+ {
+ sal_Int32 nRead;
+ sal_Int32 nBufferSize = 32767;
+ Sequence < sal_Int8 > aSequence ( nBufferSize );
+ Reference< XInputStream > aTempInput = aTempCont.openStream();
+
+ do
+ {
+ nRead = aTempInput->readBytes ( aSequence, nBufferSize );
+ if ( nRead < nBufferSize )
+ {
+ Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
+ rOutStream->writeBytes ( aTempBuf );
+ }
+ else
+ rOutStream->writeBytes ( aSequence );
+ }
+ while ( nRead == nBufferSize );
+
+ // remove temporary file
+ if ( pImp->pTempFile )
+ {
+ pImp->pTempFile->EnableKillingFile( sal_True );
+ delete pImp->pTempFile;
+ pImp->pTempFile = NULL;
+ }
+ }
+ catch( Exception& )
+ {}
+ }
+ }
+ else
+ {
+ DBG_ERROR( "Illegal Output stream parameter!\n" );
+ SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+
+ // free the reference
+ if ( pSet )
+ pSet->ClearItem( SID_OUTPUTSTREAM );
+
+ return;
+ }
+
+ GetContent();
+ if ( !pImp->aContent.get().is() )
+ {
+ eError = ERRCODE_IO_NOTEXISTS;
+ return;
+ }
+
+ SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize, SfxInt32Item, SID_SEGMENTSIZE, sal_False);
+ if ( pSegmentSize )
+ {
+ // this file must be stored into a disk spanned package
+ try
+ {
+ uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetStorageFromURL( GetName(),
+ embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
+
+ // set segment size property; package will automatically be divided in pieces fitting
+ // into this size
+ ::com::sun::star::uno::Any aAny;
+ aAny <<= pSegmentSize->GetValue();
+
+ uno::Reference < beans::XPropertySet > xSet( pImp->xStorage, uno::UNO_QUERY );
+ xSet->setPropertyValue( String::CreateFromAscii("SegmentSize"), aAny );
+
+ // copy the temporary storage into the disk spanned package
+ GetStorage()->copyToStorage( xStor );
+ uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+
+ }
+ catch ( uno::Exception& )
+ {
+ //TODO/MBA: error handling
+ }
+ return;
+ }
+
+ INetURLObject aDest( GetURLObject() );
+
+ // source is the temp file written so far
+ INetURLObject aSource( aNameURL );
+
+ // a special case, an interaction handler should be used for
+ // authentication in case it is available
+ Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
+ Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
+ if (xInteractionHandler.is())
+ xComEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler,
+ Reference< ::com::sun::star::ucb::XProgressHandler >() );
+
+ if ( ::utl::LocalFileHelper::IsLocalFile( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) || !aDest.removeSegment() )
+ {
+ TransactedTransferForFS_Impl( aSource, aDest, xComEnv );
+ }
+ else
+ {
+ // create content for the parent folder and call transfer on that content with the source content
+ // and the destination file name as parameters
+ ::ucbhelper::Content aSourceContent;
+ ::ucbhelper::Content aTransferContent;
+
+ String aFileName = GetLongName();
+ if ( !aFileName.Len() )
+ aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
+
+ try
+ {
+ aTransferContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
+ }
+ catch (const ::com::sun::star::ucb::ContentCreationException& ex)
+ {
+ eError = ERRCODE_IO_GENERAL;
+ if (
+ (ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER ) ||
+ (ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
+ )
+ {
+ eError = ERRCODE_IO_NOTEXISTSPATH;
+ }
+ }
+ catch (const ::com::sun::star::uno::Exception&)
+ {
+ eError = ERRCODE_IO_GENERAL;
+ }
+
+ if ( !eError || (eError & ERRCODE_WARNING_MASK) )
+ {
+ // free resources, otherwise the transfer may fail
+ if ( pImp->xStorage.is() )
+ CloseStorage();
+
+ CloseStreams_Impl();
+
+ ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent );
+
+ // check for external parameters that may customize the handling of NameClash situations
+ SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
+ SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
+ sal_Int32 nNameClash;
+ if ( pOverWrite && !pOverWrite->GetValue() )
+ // argument says: never overwrite
+ nNameClash = NameClash::ERROR;
+ else if ( pRename && pRename->GetValue() )
+ // argument says: rename file
+ nNameClash = NameClash::RENAME;
+ else
+ // default is overwrite existing files
+ nNameClash = NameClash::OVERWRITE;
+
+ try
+ {
+ if (!aTransferContent.transferContent( aSourceContent, ::ucbhelper::InsertOperation_COPY, aFileName, nNameClash ))
+ eError = ERRCODE_IO_GENERAL;
+ }
+ catch ( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ eError = ERRCODE_ABORT;
+ }
+ catch ( ::com::sun::star::ucb::CommandFailedException& )
+ {
+ eError = ERRCODE_ABORT;
+ }
+ catch ( ::com::sun::star::ucb::InteractiveIOException& r )
+ {
+ if ( r.Code == IOErrorCode_ACCESS_DENIED )
+ eError = ERRCODE_IO_ACCESSDENIED;
+ else if ( r.Code == IOErrorCode_NOT_EXISTING )
+ eError = ERRCODE_IO_NOTEXISTS;
+ else if ( r.Code == IOErrorCode_CANT_READ )
+ eError = ERRCODE_IO_CANTREAD;
+ else
+ eError = ERRCODE_IO_GENERAL;
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ eError = ERRCODE_IO_GENERAL;
+ }
+
+ // do not switch from temporary file in case of nonfile protocol
+ }
+ }
+
+ if ( ( !eError || (eError & ERRCODE_WARNING_MASK) ) && !pImp->pTempFile )
+ {
+ // without a TempFile the physical and logical name should be the same after successful transfer
+ ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
+ aName );
+ pImp->m_bSalvageMode = sal_False;
+ }
+ }
+}
+
+//------------------------------------------------------------------
+void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent,
+ const String& aPrefix,
+ const String& aExtension,
+ const String& aDestDir )
+{
+ RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoInternalBackup_Impl( with destdir )" );
+
+ if ( pImp->m_aBackupURL.getLength() )
+ return; // the backup was done already
+
+ ::utl::TempFile aTransactTemp( aPrefix, &aExtension, &aDestDir );
+ aTransactTemp.EnableKillingFile( sal_False );
+
+ INetURLObject aBackObj( aTransactTemp.GetURL() );
+ ::rtl::OUString aBackupName = aBackObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
+
+ Reference < ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
+ ::ucbhelper::Content aBackupCont;
+ if( ::ucbhelper::Content::create( aDestDir, xDummyEnv, aBackupCont ) )
+ {
+ try
+ {
+ if( aBackupCont.transferContent( aOriginalContent,
+ ::ucbhelper::InsertOperation_COPY,
+ aBackupName,
+ NameClash::OVERWRITE ) )
+ {
+ pImp->m_aBackupURL = aBackObj.GetMainURL( INetURLObject::NO_DECODE );
+ pImp->m_bRemoveBackup = sal_True;
+ }
+ }
+ catch( Exception& )
+ {}
+ }
+
+ if ( !pImp->m_aBackupURL.getLength() )
+ aTransactTemp.EnableKillingFile( sal_True );
+}
+
+//------------------------------------------------------------------
+void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent )
+{
+ if ( pImp->m_aBackupURL.getLength() )
+ return; // the backup was done already
+
+ ::rtl::OUString aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT,
+ true,
+ INetURLObject::NO_DECODE );
+
+ sal_Int32 nPrefixLen = aFileName.lastIndexOf( '.' );
+ String aPrefix = ( nPrefixLen == -1 ) ? aFileName : aFileName.copy( 0, nPrefixLen );
+ String aExtension = ( nPrefixLen == -1 ) ? String() : String(aFileName.copy( nPrefixLen ));
+ String aBakDir = SvtPathOptions().GetBackupPath();
+
+ DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aBakDir );
+
+ if ( !pImp->m_aBackupURL.getLength() )
+ {
+ // the copiing to the backup catalog failed ( for example because
+ // of using an encrypted partition as target catalog )
+ // since the user did not specify to make backup explicitly
+ // office should try to make backup in another place,
+ // target catalog does not look bad for this case ( and looks
+ // to be the only way for encrypted partitions )
+
+ INetURLObject aDest = GetURLObject();
+ if ( aDest.removeSegment() )
+ DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aDest.GetMainURL( INetURLObject::NO_DECODE ) );
+ }
+}
+
+
+//------------------------------------------------------------------
+void SfxMedium::DoBackup_Impl()
+{
+ RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoBackup_Impl" );
+
+ // source file name is the logical name of this medium
+ INetURLObject aSource( GetURLObject() );
+
+ // there is nothing to backup in case source file does not exist
+ if ( !::utl::UCBContentHelper::IsDocument( aSource.GetMainURL( INetURLObject::NO_DECODE ) ) )
+ return;
+
+ sal_Bool bSuccess = sal_False;
+
+ // get path for backups
+ String aBakDir = SvtPathOptions().GetBackupPath();
+ if( aBakDir.Len() )
+ {
+ // create content for the parent folder ( = backup folder )
+ ::ucbhelper::Content aContent;
+ Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
+ if( ::ucbhelper::Content::create( aBakDir, xEnv, aContent ) )
+ {
+ // save as ".bak" file
+ INetURLObject aDest( aBakDir );
+ aDest.insertName( aSource.getName() );
+ aDest.setExtension( DEFINE_CONST_UNICODE( "bak" ) );
+ String aFileName = aDest.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
+
+ // create a content for the source file
+ ::ucbhelper::Content aSourceContent;
+ if ( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent ) )
+ {
+ try
+ {
+ // do the transfer ( copy source file to backup dir )
+ bSuccess = aContent.transferContent( aSourceContent,
+ ::ucbhelper::InsertOperation_COPY,
+ aFileName,
+ NameClash::OVERWRITE );
+ if( bSuccess )
+ {
+ pImp->m_aBackupURL = aDest.GetMainURL( INetURLObject::NO_DECODE );
+ pImp->m_bRemoveBackup = sal_False;
+ }
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+
+ if ( !bSuccess )
+ {
+ eError = ERRCODE_SFX_CANTCREATEBACKUP;
+ }
+}
+
+//------------------------------------------------------------------
+void SfxMedium::ClearBackup_Impl()
+{
+ if( pImp->m_bRemoveBackup )
+ {
+ // currently a document is always stored in a new medium,
+ // thus if a backup can not be removed the backup URL should not be cleaned
+ if ( pImp->m_aBackupURL.getLength() )
+ {
+ if ( ::utl::UCBContentHelper::Kill( pImp->m_aBackupURL ) )
+ // || !::utl::UCBContentHelper::IsDocument( pImp->m_aBackupURL ) );
+ {
+ pImp->m_bRemoveBackup = sal_False;
+ pImp->m_aBackupURL = ::rtl::OUString();
+ }
+ else
+ {
+
+ DBG_ERROR("Couldn't remove backup file!");
+ }
+ }
+ }
+ else
+ pImp->m_aBackupURL = ::rtl::OUString();
+}
+
+//----------------------------------------------------------------
+void SfxMedium::GetLockingStream_Impl()
+{
+ if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
+ && !pImp->m_xLockingStream.is() )
+ {
+ SFX_ITEMSET_ARG( pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, sal_False);
+ if ( pWriteStreamItem )
+ pWriteStreamItem->GetValue() >>= pImp->m_xLockingStream;
+
+ if ( !pImp->m_xLockingStream.is() )
+ {
+ // open the original document
+ uno::Sequence< beans::PropertyValue > xProps;
+ TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
+ comphelper::MediaDescriptor aMedium( xProps );
+
+ aMedium.addInputStreamOwnLock();
+
+ uno::Reference< io::XInputStream > xInputStream;
+ aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp->m_xLockingStream;
+ aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
+
+ if ( !pImp->pTempFile && !aName.Len() )
+ {
+ // the medium is still based on the original file, it makes sence to initialize the streams
+ if ( pImp->m_xLockingStream.is() )
+ pImp->xStream = pImp->m_xLockingStream;
+
+ if ( xInputStream.is() )
+ pImp->xInputStream = xInputStream;
+
+ if ( !pImp->xInputStream.is() && pImp->xStream.is() )
+ pImp->xInputStream = pImp->xStream->getInputStream();
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------
+void SfxMedium::GetMedium_Impl()
+{
+ if ( !pInStream )
+ {
+ pImp->bDownloadDone = sal_False;
+ Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
+
+ //TODO/MBA: need support for SID_STREAM
+ SFX_ITEMSET_ARG( pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, sal_False);
+ SFX_ITEMSET_ARG( pSet, pInStreamItem, SfxUnoAnyItem, SID_INPUTSTREAM, sal_False);
+ if ( pWriteStreamItem )
+ {
+ pWriteStreamItem->GetValue() >>= pImp->xStream;
+
+ if ( pInStreamItem )
+ pInStreamItem->GetValue() >>= pImp->xInputStream;
+
+ if ( !pImp->xInputStream.is() && pImp->xStream.is() )
+ pImp->xInputStream = pImp->xStream->getInputStream();
+ }
+ else if ( pInStreamItem )
+ {
+ pInStreamItem->GetValue() >>= pImp->xInputStream;
+ }
+ else
+ {
+ uno::Sequence < beans::PropertyValue > xProps;
+ String aFileName;
+ if ( aName.Len() )
+ {
+ if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aFileName ) )
+ {
+ DBG_ERROR("Physical name not convertable!");
+ }
+ }
+ else
+ aFileName = GetName();
+
+ // in case the temporary file exists the streams should be initialized from it,
+ // but the original MediaDescriptor should not be changed
+ sal_Bool bFromTempFile = ( pImp->pTempFile != NULL );
+
+ if ( !bFromTempFile )
+ {
+ GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, aFileName ) );
+ if( !(nStorOpenMode & STREAM_WRITE ) )
+ GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, TRUE ) );
+ if (xInteractionHandler.is())
+ GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER, makeAny(xInteractionHandler) ) );
+ }
+
+ if ( m_xInputStreamToLoadFrom.is() )
+ {
+ pImp->xInputStream = m_xInputStreamToLoadFrom;
+ pImp->xInputStream->skipBytes(0);
+ if(m_bIsReadOnly)
+ GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
+
+ // m_xInputStreamToLoadFrom = 0;
+ }
+ else
+ {
+ TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
+ comphelper::MediaDescriptor aMedium( xProps );
+
+ if ( pImp->m_xLockingStream.is() && !bFromTempFile )
+ {
+ // the medium is not based on the temporary file, so the original stream can be used
+ pImp->xStream = pImp->m_xLockingStream;
+ }
+ else
+ {
+ if ( bFromTempFile )
+ {
+ aMedium[comphelper::MediaDescriptor::PROP_URL()] <<= ::rtl::OUString( aFileName );
+ aMedium.erase( comphelper::MediaDescriptor::PROP_READONLY() );
+ aMedium.addInputStream();
+ }
+ else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
+ {
+ // use the special locking approach only for file URLs
+ aMedium.addInputStreamOwnLock();
+ }
+ else
+ aMedium.addInputStream();
+
+ // the ReadOnly property set in aMedium is ignored
+ // the check is done in LockOrigFileOnDemand() for file and non-file URLs
+
+ //TODO/MBA: what happens if property is not there?!
+ aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp->xStream;
+ aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp->xInputStream;
+ }
+
+ GetContent();
+ if ( !pImp->xInputStream.is() && pImp->xStream.is() )
+ pImp->xInputStream = pImp->xStream->getInputStream();
+ }
+
+ if ( !bFromTempFile )
+ {
+ //TODO/MBA: need support for SID_STREAM
+ if ( pImp->xStream.is() )
+ GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM, makeAny( pImp->xStream ) ) );
+
+ GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM, makeAny( pImp->xInputStream ) ) );
+ }
+ }
+
+ //TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
+ if ( !GetError() && !pImp->xStream.is() && !pImp->xInputStream.is() )
+ SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+
+ if ( !GetError() )
+ {
+ if ( pImp->xStream.is() )
+ pInStream = utl::UcbStreamHelper::CreateStream( pImp->xStream );
+ else if ( pImp->xInputStream.is() )
+ pInStream = utl::UcbStreamHelper::CreateStream( pImp->xInputStream );
+ }
+
+ pImp->bDownloadDone = sal_True;
+ pImp->aDoneLink.ClearPendingCall();
+ pImp->aDoneLink.Call( (void*) GetError() );
+ }
+}
+
+//----------------------------------------------------------------
+sal_Bool SfxMedium::IsRemote()
+{
+ return bRemote;
+}
+
+//------------------------------------------------------------------
+
+void SfxMedium::SetUpdatePickList(sal_Bool bVal)
+{
+ if(!pImp)
+ pImp = new SfxMedium_Impl( this );
+ pImp->bUpdatePickList = bVal;
+}
+//------------------------------------------------------------------
+
+sal_Bool SfxMedium::IsUpdatePickList() const
+{
+ return pImp? pImp->bUpdatePickList: sal_True;
+}
+//----------------------------------------------------------------
+
+void SfxMedium::SetDoneLink( const Link& rLink )
+{
+ pImp->aDoneLink = rLink;
+}
+
+//----------------------------------------------------------------
+
+void SfxMedium::SetDataAvailableLink( const Link& rLink )
+{
+ pImp->aAvailableLink = rLink;
+}
+
+//----------------------------------------------------------------
+void SfxMedium::StartDownload()
+{
+ GetInStream();
+}
+
+void SfxMedium::DownLoad( const Link& aLink )
+{
+ SetDoneLink( aLink );
+ GetInStream();
+ if ( pInStream && !aLink.IsSet() )
+ {
+ while( !pImp->bDownloadDone )
+ Application::Yield();
+ }
+}
+
+//------------------------------------------------------------------
+void SfxMedium::Init_Impl()
+/* [Beschreibung]
+ Setzt in den Logischen Namen eine gueltige ::com::sun::star::util::URL (Falls zuvor ein Filename
+ drin war) und setzt den physikalschen Namen auf den Filenamen, falls
+ vorhanden.
+ */
+
+{
+ Reference< XOutputStream > rOutStream;
+
+ // TODO/LATER: handle lifetime of storages
+ pImp->bDisposeStorage = FALSE;
+
+ SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False);
+ if ( pSalvageItem && !pSalvageItem->GetValue().Len() )
+ {
+ pSalvageItem = NULL;
+ pSet->ClearItem( SID_DOC_SALVAGE );
+ }
+
+ if( aLogicName.Len() )
+ {
+ INetURLObject aUrl( aLogicName );
+ INetProtocol eProt = aUrl.GetProtocol();
+ if ( eProt == INET_PROT_NOT_VALID )
+ {
+ DBG_ERROR ( "Unknown protocol!" );
+ }
+ else
+ {
+ if ( aUrl.HasMark() )
+ {
+ aLogicName = aUrl.GetURLNoMark( INetURLObject::NO_DECODE );
+ GetItemSet()->Put( SfxStringItem( SID_JUMPMARK, aUrl.GetMark() ) );
+ }
+
+ // try to convert the URL into a physical name - but never change a physical name
+ // physical name may be set if the logical name is changed after construction
+ if ( !aName.Len() )
+ ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aName );
+ else {
+ DBG_ASSERT( pSalvageItem, "Suspicious change of logical name!" );
+ }
+ }
+ }
+
+ if ( pSalvageItem && pSalvageItem->GetValue().Len() )
+ {
+ aLogicName = pSalvageItem->GetValue();
+ DELETEZ( pURLObj );
+ pImp->m_bSalvageMode = sal_True;
+ }
+
+ // in case output stream is by mistake here
+ // clear the reference
+ SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
+ if( pOutStreamItem
+ && ( !( pOutStreamItem->GetValue() >>= rOutStream )
+ || !aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL ) )
+ {
+ pSet->ClearItem( SID_OUTPUTSTREAM );
+ DBG_ERROR( "Unexpected Output stream parameter!\n" );
+ }
+
+ if ( aLogicName.Len() )
+ {
+ // if the logic name is set it should be set in MediaDescriptor as well
+ SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE );
+ if ( !pFileNameItem )
+ {
+ // let the ItemSet be created if necessary
+ GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, INetURLObject( aLogicName ).GetMainURL( INetURLObject::NO_DECODE ) ) );
+ }
+ }
+
+ SetIsRemote_Impl();
+}
+
+//------------------------------------------------------------------
+SfxMedium::SfxMedium()
+: IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
+
+ pFilter(0),
+ pSet(0),
+ pImp(new SfxMedium_Impl( this ))
+{
+ Init_Impl();
+}
+//------------------------------------------------------------------
+
+SfxMedium::SfxMedium( const SfxMedium& rMedium, sal_Bool bTemporary )
+: SvRefBase(),
+ IMPL_CTOR( sal_True, // bRoot, pURLObj
+ rMedium.pURLObj ? new INetURLObject(*rMedium.pURLObj) : 0 ),
+ pImp(new SfxMedium_Impl( this ))
+{
+ bDirect = rMedium.IsDirect();
+ nStorOpenMode = rMedium.GetOpenMode();
+ if ( !bTemporary )
+ aName = rMedium.aName;
+
+ pImp->bIsTemp = bTemporary;
+ DBG_ASSERT( ! rMedium.pImp->bIsTemp, "Temporaeres Medium darf nicht kopiert werden" );
+ aLogicName = rMedium.aLogicName;
+ pSet = rMedium.GetItemSet() ? new SfxItemSet(*rMedium.GetItemSet()) : 0;
+ pFilter = rMedium.pFilter;
+ Init_Impl();
+ if( bTemporary )
+ CreateTempFile( sal_True );
+}
+
+//------------------------------------------------------------------
+
+void SfxMedium::UseInteractionHandler( BOOL bUse )
+{
+ pImp->bAllowDefaultIntHdl = bUse;
+}
+
+//------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >
+SfxMedium::GetInteractionHandler()
+{
+ // if interaction isnt allowed explicitly ... return empty reference!
+ if ( !pImp->bUseInteractionHandler )
+ return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
+
+ // search a possible existing handler inside cached item set
+ if ( pSet )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xHandler;
+ SFX_ITEMSET_ARG( pSet, pHandler, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False);
+ if ( pHandler && (pHandler->GetValue() >>= xHandler) && xHandler.is() )
+ return xHandler;
+ }
+
+ // if default interaction isnt allowed explicitly ... return empty reference!
+ if ( !pImp->bAllowDefaultIntHdl )
+ return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
+
+ // otherwhise return cached default handler ... if it exist.
+ if ( pImp->xInteraction.is() )
+ return pImp->xInteraction;
+
+ // create default handler and cache it!
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
+ if ( xFactory.is() )
+ {
+ pImp->xInteraction = ::com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler >( xFactory->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), ::com::sun::star::uno::UNO_QUERY );
+ return pImp->xInteraction;
+ }
+
+ return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
+}
+
+//----------------------------------------------------------------
+
+void SfxMedium::SetFilter( const SfxFilter* pFilterP, sal_Bool /*bResetOrig*/ )
+{
+ pFilter = pFilterP;
+ pImp->nFileVersion = 0;
+}
+//----------------------------------------------------------------
+
+const SfxFilter* SfxMedium::GetOrigFilter( sal_Bool bNotCurrent ) const
+{
+ return ( pImp->pOrigFilter || bNotCurrent ) ? pImp->pOrigFilter : pFilter;
+}
+//----------------------------------------------------------------
+
+void SfxMedium::SetOrigFilter_Impl( const SfxFilter* pOrigFilter )
+{
+ pImp->pOrigFilter = pOrigFilter;
+}
+//------------------------------------------------------------------
+
+void SfxMedium::Close()
+{
+ if ( pImp->xStorage.is() )
+ {
+ // don't close the streams if they belong to the
+ // storage
+ //TODO/MBA: how to?! Do we need the flag?!
+ /*
+ const SvStream *pStream = aStorage->GetSvStream();
+ if ( pStream && pStream == pInStream )
+ {
+ CloseZipStorage_Impl();
+ pInStream = NULL;
+ pImp->xInputStream = Reference < XInputStream >();
+ pImp->xLockBytes.Clear();
+ if ( pSet )
+ pSet->ClearItem( SID_INPUTSTREAM );
+ aStorage->SetDeleteStream( TRUE );
+ }
+ else if ( pStream && pStream == pOutStream )
+ {
+ pOutStream = NULL;
+ aStorage->SetDeleteStream( TRUE );
+ } */
+
+ CloseStorage();
+ }
+
+ CloseStreams_Impl();
+
+ UnlockFile( sal_False );
+}
+
+void SfxMedium::CloseAndRelease()
+{
+ if ( pImp->xStorage.is() )
+ {
+ // don't close the streams if they belong to the
+ // storage
+ //TODO/MBA: how to?! Do we need the flag?!
+ /*
+ const SvStream *pStream = aStorage->GetSvStream();
+ if ( pStream && pStream == pInStream )
+ {
+ CloseZipStorage_Impl();
+ pInStream = NULL;
+ pImp->xInputStream = Reference < XInputStream >();
+ pImp->xLockBytes.Clear();
+ if ( pSet )
+ pSet->ClearItem( SID_INPUTSTREAM );
+ aStorage->SetDeleteStream( TRUE );
+ }
+ else if ( pStream && pStream == pOutStream )
+ {
+ pOutStream = NULL;
+ aStorage->SetDeleteStream( TRUE );
+ } */
+
+ CloseStorage();
+ }
+
+ CloseAndReleaseStreams_Impl();
+
+ UnlockFile( sal_True );
+}
+
+void SfxMedium::UnlockFile( sal_Bool bReleaseLockStream )
+{
+ if ( pImp->m_xLockingStream.is() )
+ {
+ if ( bReleaseLockStream )
+ {
+ try
+ {
+ uno::Reference< io::XInputStream > xInStream = pImp->m_xLockingStream->getInputStream();
+ uno::Reference< io::XOutputStream > xOutStream = pImp->m_xLockingStream->getOutputStream();
+ if ( xInStream.is() )
+ xInStream->closeInput();
+ if ( xOutStream.is() )
+ xOutStream->closeOutput();
+ }
+ catch( uno::Exception& )
+ {}
+ }
+
+ pImp->m_xLockingStream = uno::Reference< io::XStream >();
+ }
+
+ if ( pImp->m_bLocked )
+ {
+ try
+ {
+ pImp->m_bLocked = sal_False;
+ ::svt::DocumentLockFile aLockFile( aLogicName );
+ // TODO/LATER: A warning could be shown in case the file is not the own one
+ aLockFile.RemoveFile();
+ }
+ catch( uno::Exception& )
+ {}
+ }
+}
+
+void SfxMedium::CloseAndReleaseStreams_Impl()
+{
+ CloseZipStorage_Impl();
+
+ uno::Reference< io::XInputStream > xInToClose = pImp->xInputStream;
+ uno::Reference< io::XOutputStream > xOutToClose;
+ if ( pImp->xStream.is() )
+ {
+ xOutToClose = pImp->xStream->getOutputStream();
+
+ // if the locking stream is closed here the related member should be cleaned
+ if ( pImp->xStream == pImp->m_xLockingStream )
+ pImp->m_xLockingStream = uno::Reference< io::XStream >();
+ }
+
+ // The probably exsisting SvStream wrappers should be closed first
+ CloseStreams_Impl();
+
+ // in case of salvage mode the storage is based on the streams
+ if ( !pImp->m_bSalvageMode )
+ {
+ try
+ {
+ if ( xInToClose.is() )
+ xInToClose->closeInput();
+ if ( xOutToClose.is() )
+ xOutToClose->closeOutput();
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+}
+
+//------------------------------------------------------------------
+void SfxMedium::CloseStreams_Impl()
+{
+ CloseInStream_Impl();
+ CloseOutStream_Impl();
+
+ if ( pSet )
+ pSet->ClearItem( SID_CONTENT );
+
+ pImp->aContent = ::ucbhelper::Content();
+}
+
+//------------------------------------------------------------------
+
+void SfxMedium::RefreshName_Impl()
+{
+#if 0 //(dv)
+ if ( pImp->aContent.get().is() )
+ {
+ String aNameP = pImp->xAnchor->GetViewURL();
+ pImp->aOrigURL = aNameP;
+ aLogicName = aNameP;
+ DELETEZ( pURLObj );
+ if (aLogicName.Len())
+ aLogicName = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
+ SetIsRemote_Impl();
+ }
+#endif //(dv)
+}
+
+void SfxMedium::SetIsRemote_Impl()
+{
+ INetURLObject aObj( GetName() );
+ switch( aObj.GetProtocol() )
+ {
+ case INET_PROT_FTP:
+ case INET_PROT_HTTP:
+ case INET_PROT_HTTPS:
+ case INET_PROT_POP3:
+ case INET_PROT_NEWS:
+ case INET_PROT_IMAP:
+// case INET_PROT_OUT:
+ case INET_PROT_VIM:
+ bRemote = TRUE; break;
+ default:
+ bRemote = ( GetName().CompareToAscii( "private:msgid", 13 ) == COMPARE_EQUAL );
+ break;
+ }
+
+ // Da Dateien, die Remote geschrieben werden zur Uebertragung auch
+ // gelesen werden koennen muessen
+ if( bRemote )
+ nStorOpenMode |= STREAM_READ;
+}
+
+
+
+void SfxMedium::SetName( const String& aNameP, sal_Bool bSetOrigURL )
+{
+ if( !pImp->aOrigURL.Len() )
+ pImp->aOrigURL = aLogicName;
+ if( bSetOrigURL )
+ pImp->aOrigURL = aNameP;
+ aLogicName = aNameP;
+ DELETEZ( pURLObj );
+ pImp->aContent = ::ucbhelper::Content();
+ Init_Impl();
+}
+
+//----------------------------------------------------------------
+const String& SfxMedium::GetOrigURL() const
+{
+ return !pImp->aOrigURL.Len() ? (String &)aLogicName : pImp->aOrigURL;
+}
+
+//----------------------------------------------------------------
+
+void SfxMedium::SetPhysicalName_Impl( const String& rNameP )
+{
+ if ( rNameP != aName )
+ {
+ if( pImp->pTempFile )
+ {
+ delete pImp->pTempFile;
+ pImp->pTempFile = NULL;
+ }
+
+ if ( aName.Len() || rNameP.Len() )
+ pImp->aContent = ::ucbhelper::Content();
+
+ aName = rNameP;
+ bTriedStorage = sal_False;
+ pImp->bIsStorage = sal_False;
+ }
+}
+
+//------------------------------------------------------------------
+void SfxMedium::SetTemporary( sal_Bool bTemp )
+{
+ pImp->bIsTemp = bTemp;
+}
+
+//------------------------------------------------------------------
+sal_Bool SfxMedium::IsTemporary() const
+{
+ return pImp->bIsTemp;
+}
+
+//------------------------------------------------------------------
+
+sal_Bool SfxMedium::Exists( sal_Bool /*bForceSession*/ )
+{
+ DBG_ERROR( "Not implemented!" );
+ return sal_True;
+}
+
+//------------------------------------------------------------------
+
+void SfxMedium::ReOpen()
+{
+ BOOL bUseInteractionHandler = pImp->bUseInteractionHandler;
+ pImp->bUseInteractionHandler = FALSE;
+ GetMedium_Impl();
+ pImp->bUseInteractionHandler = bUseInteractionHandler;
+}
+
+//------------------------------------------------------------------
+
+void SfxMedium::CompleteReOpen()
+{
+ // do not use temporary file for reopen and in case of success throw the temporary file away
+ BOOL bUseInteractionHandler = pImp->bUseInteractionHandler;
+ pImp->bUseInteractionHandler = FALSE;
+
+ ::utl::TempFile* pTmpFile = NULL;
+ if ( pImp->pTempFile )
+ {
+ pTmpFile = pImp->pTempFile;
+ pImp->pTempFile = NULL;
+ aName = String();
+ }
+
+ GetMedium_Impl();
+
+ if ( GetError() )
+ {
+ if ( pImp->pTempFile )
+ {
+ pImp->pTempFile->EnableKillingFile( sal_True );
+ delete pImp->pTempFile;
+ }
+ pImp->pTempFile = pTmpFile;
+ if ( pImp->pTempFile )
+ aName = pImp->pTempFile->GetFileName();
+ }
+ else
+ {
+ pTmpFile->EnableKillingFile( sal_True );
+ delete pTmpFile;
+
+ }
+
+ pImp->bUseInteractionHandler = bUseInteractionHandler;
+}
+
+//------------------------------------------------------------------
+SfxMedium::SfxMedium
+(
+ const String &rName, StreamMode nOpenMode, sal_Bool bDirectP,
+ const SfxFilter *pFlt, SfxItemSet *pInSet
+)
+: IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
+ pFilter(pFlt),
+ pSet( pInSet ),
+ pImp(new SfxMedium_Impl( this ))
+{
+ aLogicName = rName;
+ nStorOpenMode = nOpenMode;
+ bDirect = bDirectP;
+ Init_Impl();
+}
+
+
+SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
+ : IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
+ pFilter(0),
+ pSet(0),
+ pImp(new SfxMedium_Impl( this ))
+{
+ SfxAllItemSet *pParams = new SfxAllItemSet( SFX_APP()->GetPool() );
+ pSet = pParams;
+ TransformParameters( SID_OPENDOC, aArgs, *pParams );
+
+ String aFilterName;
+ SFX_ITEMSET_ARG( pSet, pFilterNameItem, SfxStringItem, SID_FILTER_NAME, sal_False );
+ if( pFilterNameItem )
+ aFilterName = pFilterNameItem->GetValue();
+ pFilter = SFX_APP()->GetFilterMatcher().GetFilter4FilterName( aFilterName );
+
+ sal_Bool bSalvage = sal_False;
+ SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False );
+ if( pSalvageItem )
+ {
+ // QUESTION: there is some treatment of Salvage in Init_Impl; align!
+ bSalvage = sal_True;
+ if ( pSalvageItem->GetValue().Len() )
+ {
+ // if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
+ // that must be copied here
+
+ SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE );
+ if (!pFileNameItem) throw uno::RuntimeException();
+ ::rtl::OUString aNewTempFileURL = SfxMedium::CreateTempCopyWithExt( pFileNameItem->GetValue() );
+ if ( aNewTempFileURL.getLength() )
+ {
+ pSet->Put( SfxStringItem( SID_FILE_NAME, aNewTempFileURL ) );
+ pSet->ClearItem( SID_INPUTSTREAM );
+ pSet->ClearItem( SID_STREAM );
+ pSet->ClearItem( SID_CONTENT );
+ }
+ else
+ {
+ OSL_ENSURE( sal_False, "Can not create a new temporary file for crash recovery!\n" );
+ }
+ }
+ }
+
+ BOOL bReadOnly = FALSE;
+ SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, FALSE );
+ if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
+ bReadOnly = TRUE;
+
+ SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE );
+ if (!pFileNameItem) throw uno::RuntimeException();
+ aLogicName = pFileNameItem->GetValue();
+ nStorOpenMode = bReadOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
+ bDirect = FALSE;
+ Init_Impl();
+}
+
+
+//------------------------------------------------------------------
+
+SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const String& rBaseURL, const SfxItemSet* p, sal_Bool bRootP )
+: IMPL_CTOR( bRootP, 0 ), // bRoot, pURLObj
+ pSet(0),
+ pImp( new SfxMedium_Impl( this ))
+{
+ String aType = SfxFilter::GetTypeFromStorage( rStor );
+ pFilter = SFX_APP()->GetFilterMatcher().GetFilter4EA( aType );
+ DBG_ASSERT( pFilter, "No Filter for storage found!" );
+
+ Init_Impl();
+ pImp->xStorage = rStor;
+ pImp->bDisposeStorage = FALSE;
+
+ // always take BaseURL first, could be overwritten by ItemSet
+ GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
+ if ( p )
+ GetItemSet()->Put( *p );
+}
+
+//------------------------------------------------------------------
+
+SfxMedium::~SfxMedium()
+{
+ /* Attention
+ Don't enable CancelTransfers() till you know that the writer/web has changed his asynchronous load
+ behaviour. Otherwhise may StyleSheets inside a html file will be loaded at the right time.
+ => further the help will be empty then ... #100490#
+ */
+ //CancelTransfers();
+
+ // if there is a requirement to clean the backup this is the last possibility to do it
+ ClearBackup_Impl();
+
+ Close();
+
+ delete pSet;
+
+ if( pImp->bIsTemp && aName.Len() )
+ {
+ String aTemp;
+ if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aTemp ))
+ {
+ DBG_ERROR("Physical name not convertable!");
+ }
+
+ if ( !::utl::UCBContentHelper::Kill( aTemp ) )
+ {
+ DBG_ERROR("Couldn't remove temporary file!");
+ }
+ }
+
+ pFilter = 0;
+
+ delete pURLObj;
+ delete pImp;
+}
+
+//------------------------------------------------------------------
+void SfxMedium::SetItemSet(SfxItemSet *pNewSet)
+{
+ delete pSet;
+ pSet = pNewSet;
+}
+
+//----------------------------------------------------------------
+const INetURLObject& SfxMedium::GetURLObject() const
+{
+ if( !pURLObj )
+ {
+ SfxMedium* pThis = const_cast < SfxMedium* > (this);
+ pThis->pURLObj = new INetURLObject( aLogicName );
+ if ( pThis->pURLObj->HasMark() )
+ (*pThis->pURLObj) = INetURLObject( aLogicName ).GetURLNoMark();
+ }
+
+ return *pURLObj;
+}
+
+//----------------------------------------------------------------
+
+const String& SfxMedium::GetPreRedirectedURL() const
+{
+ return pImp->aPreRedirectionURL;
+}
+//----------------------------------------------------------------
+
+sal_uInt32 SfxMedium::GetMIMEAndRedirect( String& /*rName*/ )
+{
+/* dv !!!! not needed any longer ?
+ INetProtocol eProt = GetURLObject().GetProtocol();
+ if( eProt == INET_PROT_FTP && SvBinding::ShouldUseFtpProxy( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
+ {
+ Any aAny( UCB_Helper::GetProperty( GetContent(), WID_FLAG_IS_FOLDER ) );
+ sal_Bool bIsFolder = FALSE;
+ if ( ( aAny >>= bIsFolder ) && bIsFolder )
+ return ERRCODE_NONE;
+ }
+
+ GetMedium_Impl();
+ if( !eError && pImp->xBinding.Is() )
+ {
+ eError = pImp->xBinding->GetMimeType( rName );
+
+ // Wir koennen keine Parameter wie CharSets usw.
+ rName = rName.GetToken( 0, ';' );
+ if( !eError )
+ {
+ if( !pImp->aPreRedirectionURL.Len() )
+ pImp->aPreRedirectionURL = aLogicName;
+ SetName( pImp->xBinding->GetRedirectedURL() );
+ }
+ pImp->aExpireTime = pImp->xBinding->GetExpireDateTime();
+ }
+ return eError;
+*/
+ return 0;
+}
+
+//----------------------------------------------------------------
+
+void SfxMedium::SetReferer( const String& rRefer )
+{
+ pImp->aReferer = rRefer;
+}
+//----------------------------------------------------------------
+
+const String& SfxMedium::GetReferer( ) const
+{
+ return pImp->aReferer;
+}
+
+//----------------------------------------------------------------
+
+void SfxMedium::SetExpired_Impl( const DateTime& rDateTime )
+{
+ pImp->aExpireTime = rDateTime;
+}
+//----------------------------------------------------------------
+
+sal_Bool SfxMedium::IsExpired() const
+{
+ return pImp->aExpireTime.IsValid() && pImp->aExpireTime < DateTime();
+}
+//----------------------------------------------------------------
+
+void SfxMedium::ForceSynchronStream_Impl( sal_Bool bForce )
+{
+ if( pInStream )
+ {
+ SvLockBytes* pBytes = pInStream->GetLockBytes();
+ if( pBytes )
+ pBytes->SetSynchronMode( bForce );
+ }
+ pImp->bForceSynchron = bForce;
+}
+
+//----------------------------------------------------------------
+SfxFrame* SfxMedium::GetLoadTargetFrame() const
+{
+ return pImp->wLoadTargetFrame;
+}
+//----------------------------------------------------------------
+
+void SfxMedium::SetLoadTargetFrame(SfxFrame* pFrame )
+{
+ pImp->wLoadTargetFrame = pFrame;
+}
+//----------------------------------------------------------------
+
+void SfxMedium::SetStorage_Impl( const uno::Reference < embed::XStorage >& rStor )
+{
+ pImp->xStorage = rStor;
+}
+//----------------------------------------------------------------
+
+SfxItemSet* SfxMedium::GetItemSet() const
+{
+ // this method *must* return an ItemSet, returning NULL can cause crashes
+ if( !pSet )
+ ((SfxMedium*)this)->pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
+ return pSet;
+}
+//----------------------------------------------------------------
+
+SvKeyValueIterator* SfxMedium::GetHeaderAttributes_Impl()
+{
+ if( !pImp->xAttributes.Is() )
+ {
+ pImp->xAttributes = SvKeyValueIteratorRef( new SvKeyValueIterator );
+
+ if ( GetContent().is() )
+ {
+ pImp->bIsCharsetInitialized = sal_True;
+
+ try
+ {
+ Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
+ ::rtl::OUString aContentType;
+ aAny >>= aContentType;
+
+ pImp->xAttributes->Append( SvKeyValue( ::rtl::OUString::createFromAscii( "content-type" ), aContentType ) );
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+ }
+
+ return pImp->xAttributes;
+}
+//----------------------------------------------------------------
+
+SvCompatWeakHdl* SfxMedium::GetHdl()
+{
+ return pImp->GetHdl();
+}
+
+sal_Bool SfxMedium::IsDownloadDone_Impl()
+{
+ return pImp->bDownloadDone;
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SfxMedium::GetInputStream()
+{
+ if ( !pImp->xInputStream.is() )
+ GetMedium_Impl();
+ return pImp->xInputStream;
+}
+
+const uno::Sequence < util::RevisionTag >& SfxMedium::GetVersionList( bool _bNoReload )
+{
+ // if the medium has no name, then this medium should represent a new document and can have no version info
+ if ( ( !_bNoReload || !pImp->m_bVersionsAlreadyLoaded ) && !pImp->aVersions.getLength() &&
+ ( aName.Len() || aLogicName.Len() ) && GetStorage().is() )
+ {
+ uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
+ ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
+ if ( xReader.is() )
+ {
+ try
+ {
+ pImp->aVersions = xReader->load( GetStorage() );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+ }
+
+ if ( !pImp->m_bVersionsAlreadyLoaded )
+ pImp->m_bVersionsAlreadyLoaded = sal_True;
+
+ return pImp->aVersions;
+}
+
+uno::Sequence < util::RevisionTag > SfxMedium::GetVersionList( const uno::Reference < embed::XStorage >& xStorage )
+{
+ uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
+ ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
+ if ( xReader.is() )
+ {
+ try
+ {
+ return xReader->load( xStorage );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+
+ return uno::Sequence < util::RevisionTag >();
+}
+
+sal_uInt16 SfxMedium::AddVersion_Impl( util::RevisionTag& rRevision )
+{
+ if ( GetStorage().is() )
+ {
+ // Einen eindeutigen Namen f"ur den Stream ermitteln
+ SvULongs aLongs;
+ sal_Int32 nLength = pImp->aVersions.getLength();
+ for ( sal_Int32 m=0; m<nLength; m++ )
+ {
+ sal_uInt32 nVer = (sal_uInt32) String( pImp->aVersions[m].Identifier ).Copy(7).ToInt32();
+ sal_uInt16 n;
+ for ( n=0; n<aLongs.Count(); n++ )
+ if ( nVer<aLongs[n] )
+ break;
+
+ aLongs.Insert( nVer, n );
+ }
+
+ sal_uInt16 nKey;
+ for ( nKey=0; nKey<aLongs.Count(); nKey++ )
+ if ( aLongs[nKey] > ( ULONG ) nKey+1 )
+ break;
+
+ String aRevName = DEFINE_CONST_UNICODE( "Version" );
+ aRevName += String::CreateFromInt32( nKey + 1 );
+ pImp->aVersions.realloc( nLength+1 );
+ rRevision.Identifier = aRevName;
+ pImp->aVersions[nLength] = rRevision;
+ return nKey;
+ }
+
+ return 0;
+}
+
+sal_Bool SfxMedium::RemoveVersion_Impl( const ::rtl::OUString& rName )
+{
+ if ( !pImp->aVersions.getLength() )
+ return sal_False;
+
+ sal_Int32 nLength = pImp->aVersions.getLength();
+ for ( sal_Int32 n=0; n<nLength; n++ )
+ {
+ if ( pImp->aVersions[n].Identifier == rName )
+ {
+ for ( sal_Int32 m=n; m<nLength-1; m++ )
+ pImp->aVersions[m] = pImp->aVersions[m+1];
+ pImp->aVersions.realloc(nLength-1);
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+sal_Bool SfxMedium::TransferVersionList_Impl( SfxMedium& rMedium )
+{
+ if ( rMedium.pImp->aVersions.getLength() )
+ {
+ pImp->aVersions = rMedium.pImp->aVersions;
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+sal_Bool SfxMedium::SaveVersionList_Impl( sal_Bool /*bUseXML*/ )
+{
+ if ( GetStorage().is() )
+ {
+ if ( !pImp->aVersions.getLength() )
+ return sal_True;
+
+ uno::Reference < document::XDocumentRevisionListPersistence > xWriter( comphelper::getProcessServiceFactory()->createInstance(
+ ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
+ if ( xWriter.is() )
+ {
+ try
+ {
+ xWriter->store( GetStorage(), pImp->aVersions );
+ return sal_True;
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+ }
+
+ return sal_False;
+}
+
+//----------------------------------------------------------------
+sal_Bool SfxMedium::IsReadOnly()
+{
+ sal_Bool bReadOnly = sal_False;
+
+ // a) ReadOnly filter cant produce read/write contents!
+ bReadOnly = (
+ (pFilter ) &&
+ ((pFilter->GetFilterFlags() & SFX_FILTER_OPENREADONLY) == SFX_FILTER_OPENREADONLY)
+ );
+
+ // b) if filter allow read/write contents .. check open mode of the storage
+ if (!bReadOnly)
+ bReadOnly = !( GetOpenMode() & STREAM_WRITE );
+
+ // c) the API can force the readonly state!
+ if (!bReadOnly)
+ {
+ SFX_ITEMSET_ARG( GetItemSet(), pItem, SfxBoolItem, SID_DOC_READONLY, sal_False);
+ if (pItem)
+ bReadOnly = pItem->GetValue();
+ }
+
+ return bReadOnly;
+}
+
+//----------------------------------------------------------------
+sal_Bool SfxMedium::SetWritableForUserOnly( const ::rtl::OUString& aURL )
+{
+ // UCB does not allow to allow write access only for the user,
+ // use osl API
+ sal_Bool bResult = sal_False;
+
+ ::osl::DirectoryItem aDirItem;
+ if ( ::osl::DirectoryItem::get( aURL, aDirItem ) == ::osl::FileBase::E_None )
+ {
+ ::osl::FileStatus aFileStatus( FileStatusMask_Attributes );
+ if ( aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None
+ && aFileStatus.isValid( FileStatusMask_Attributes ) )
+ {
+ sal_uInt64 nAttributes = aFileStatus.getAttributes();
+
+ nAttributes &= ~(Attribute_OwnWrite |
+ Attribute_GrpWrite |
+ Attribute_OthWrite |
+ Attribute_ReadOnly);
+ nAttributes |= Attribute_OwnWrite;
+
+ bResult = ( osl::File::setAttributes( aURL, nAttributes ) == ::osl::FileBase::E_None );
+ }
+ }
+
+ return bResult;
+}
+
+//----------------------------------------------------------------
+void SfxMedium::CreateTempFile( sal_Bool bReplace )
+{
+ if ( pImp->pTempFile )
+ {
+ if ( !bReplace )
+ return;
+
+ DELETEZ( pImp->pTempFile );
+ aName = String();
+ }
+
+ pImp->pTempFile = new ::utl::TempFile();
+ pImp->pTempFile->EnableKillingFile( sal_True );
+ aName = pImp->pTempFile->GetFileName();
+ ::rtl::OUString aTmpURL = pImp->pTempFile->GetURL();
+ if ( !aName.Len() || !aTmpURL.getLength() )
+ {
+ SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ return;
+ }
+
+ if ( !( nStorOpenMode & STREAM_TRUNC ) )
+ {
+ sal_Bool bTransferSuccess = sal_False;
+
+ if ( GetContent().is()
+ && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
+ && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
+ {
+ // if there is already such a document, we should copy it
+ // if it is a file system use OS copy process
+ try
+ {
+ uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
+ INetURLObject aTmpURLObj( aTmpURL );
+ ::rtl::OUString aFileName = aTmpURLObj.getName( INetURLObject::LAST_SEGMENT,
+ true,
+ INetURLObject::DECODE_WITH_CHARSET );
+ if ( aFileName.getLength() && aTmpURLObj.removeSegment() )
+ {
+ ::ucbhelper::Content aTargetContent( aTmpURLObj.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
+ if ( aTargetContent.transferContent( pImp->aContent, ::ucbhelper::InsertOperation_COPY, aFileName, NameClash::OVERWRITE ) )
+ {
+ SetWritableForUserOnly( aTmpURL );
+ bTransferSuccess = sal_True;
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {}
+
+ if ( bTransferSuccess )
+ {
+ CloseOutStream();
+ CloseInStream();
+ }
+ }
+
+ if ( !bTransferSuccess && pInStream )
+ {
+ // the case when there is no URL-access available or this is a remote protocoll
+ // but there is an input stream
+ GetOutStream();
+ if ( pOutStream )
+ {
+ char *pBuf = new char [8192];
+ sal_uInt32 nErr = ERRCODE_NONE;
+
+ pInStream->Seek(0);
+ pOutStream->Seek(0);
+
+ while( !pInStream->IsEof() && nErr == ERRCODE_NONE )
+ {
+ sal_uInt32 nRead = pInStream->Read( pBuf, 8192 );
+ nErr = pInStream->GetError();
+ pOutStream->Write( pBuf, nRead );
+ }
+
+ bTransferSuccess = sal_True;
+ delete[] pBuf;
+ CloseInStream();
+ }
+ CloseOutStream_Impl();
+ }
+ else
+ {
+ // Quite strange design, but currently it is expected that in this case no transfer happens
+ // TODO/LATER: get rid of this inconsistent part of the call design
+ bTransferSuccess = sal_True;
+ CloseInStream();
+ }
+
+ if ( !bTransferSuccess )
+ {
+ SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ return;
+ }
+ }
+
+ CloseStorage();
+}
+
+//----------------------------------------------------------------
+void SfxMedium::CreateTempFileNoCopy()
+{
+ // this call always replaces the existing temporary file
+ if ( pImp->pTempFile )
+ delete pImp->pTempFile;
+
+ pImp->pTempFile = new ::utl::TempFile();
+ pImp->pTempFile->EnableKillingFile( sal_True );
+ aName = pImp->pTempFile->GetFileName();
+ if ( !aName.Len() )
+ {
+ SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ return;
+ }
+
+ CloseOutStream_Impl();
+ CloseStorage();
+}
+
+::rtl::OUString SfxMedium::GetCharset()
+{
+ if( !pImp->bIsCharsetInitialized )
+ {
+ // Set an error in case there is no content?
+ if ( GetContent().is() )
+ {
+ pImp->bIsCharsetInitialized = sal_True;
+
+ try
+ {
+ Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
+ ::rtl::OUString aField;
+ aAny >>= aField;
+
+ ::rtl::OString sContent = ::rtl::OUStringToOString( aField, RTL_TEXTENCODING_ASCII_US );
+ ByteString sType, sSubType;
+ INetContentTypeParameterList aParameters;
+
+ if( INetContentTypes::parse( sContent, sType, sSubType, &aParameters ) )
+ {
+ const INetContentTypeParameter * pCharset = aParameters.find("charset");
+ if (pCharset != 0)
+ pImp->aCharset = pCharset->m_sValue;
+ }
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+ }
+
+ return pImp->aCharset;
+}
+
+void SfxMedium::SetCharset( ::rtl::OUString aChs )
+{
+ pImp->bIsCharsetInitialized = sal_True;
+ pImp->aCharset = aChs;
+}
+
+sal_Bool SfxMedium::SignContents_Impl( sal_Bool bScriptingContent, const ::rtl::OUString& aODFVersion, sal_Bool bHasValidDocumentSignature )
+{
+ sal_Bool bChanges = FALSE;
+
+ // the medium should be closed to be able to sign, the caller is responsible to close it
+ if ( !IsOpen() && !GetError() )
+ {
+ // The component should know if there was a valid document signature, since
+ // it should show a warning in this case
+ uno::Sequence< uno::Any > aArgs( 2 );
+ aArgs[0] <<= aODFVersion;
+ aArgs[1] <<= bHasValidDocumentSignature;
+ ::com::sun::star::uno::Reference< ::com::sun::star::security::XDocumentDigitalSignatures > xSigner(
+ comphelper::getProcessServiceFactory()->createInstanceWithArguments(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ),
+ aArgs ),
+ ::com::sun::star::uno::UNO_QUERY );
+
+ if ( xSigner.is() )
+ {
+ uno::Reference< embed::XStorage > xWriteableZipStor;
+ if ( !IsReadOnly() )
+ {
+ // we can reuse the temporary file if there is one already
+ CreateTempFile( sal_False );
+ GetMedium_Impl();
+
+ try
+ {
+ if ( !pImp->xStream.is() )
+ throw uno::RuntimeException();
+
+ xWriteableZipStor = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING, pImp->xStream );
+ if ( !xWriteableZipStor.is() )
+ throw uno::RuntimeException();
+
+ uno::Reference< embed::XStorage > xMetaInf = xWriteableZipStor->openStorageElement(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
+ embed::ElementModes::READWRITE );
+ if ( !xMetaInf.is() )
+ throw uno::RuntimeException();
+
+ if ( bScriptingContent )
+ {
+ // If the signature has already the document signature it will be removed
+ // after the scripting signature is inserted.
+ uno::Reference< io::XStream > xStream(
+ xMetaInf->openStreamElement( xSigner->getScriptingContentSignatureDefaultStreamName(),
+ embed::ElementModes::READWRITE ),
+ uno::UNO_SET_THROW );
+
+ if ( xSigner->signScriptingContent( GetZipStorageToSign_Impl(), xStream ) )
+ {
+ // remove the document signature if any
+ ::rtl::OUString aDocSigName = xSigner->getDocumentContentSignatureDefaultStreamName();
+ if ( aDocSigName.getLength() && xMetaInf->hasByName( aDocSigName ) )
+ xMetaInf->removeElement( aDocSigName );
+
+ uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
+ xTransact->commit();
+ xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
+ xTransact->commit();
+
+ // the temporary file has been written, commit it to the original file
+ Commit();
+ bChanges = TRUE;
+ }
+ }
+ else
+ {
+ uno::Reference< io::XStream > xStream(
+ xMetaInf->openStreamElement( xSigner->getDocumentContentSignatureDefaultStreamName(),
+ embed::ElementModes::READWRITE ),
+ uno::UNO_SET_THROW );
+
+ if ( xSigner->signDocumentContent( GetZipStorageToSign_Impl(), xStream ) )
+ {
+ uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
+ xTransact->commit();
+ xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
+ xTransact->commit();
+
+ // the temporary file has been written, commit it to the original file
+ Commit();
+ bChanges = TRUE;
+ }
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
+ }
+
+ CloseAndRelease();
+ }
+ else
+ {
+ try
+ {
+ if ( bScriptingContent )
+ xSigner->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
+ else
+ xSigner->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
+ }
+ }
+ }
+
+ ResetError();
+ }
+
+ return bChanges;
+}
+
+//----------------------------------------------------------------
+sal_uInt16 SfxMedium::GetCachedSignatureState_Impl()
+{
+ return pImp->m_nSignatureState;
+}
+
+//----------------------------------------------------------------
+void SfxMedium::SetCachedSignatureState_Impl( sal_uInt16 nState )
+{
+ pImp->m_nSignatureState = nState;
+}
+
+//----------------------------------------------------------------
+sal_Bool SfxMedium::EqualURLs( const ::rtl::OUString& aFirstURL, const ::rtl::OUString& aSecondURL )
+{
+ sal_Bool bResult = sal_False;
+
+ if ( aFirstURL.getLength() && aSecondURL.getLength() )
+ {
+ INetURLObject aFirst( aFirstURL );
+ INetURLObject aSecond( aSecondURL );
+
+ if ( aFirst.GetProtocol() != INET_PROT_NOT_VALID && aSecond.GetProtocol() != INET_PROT_NOT_VALID )
+ {
+ try
+ {
+ ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get();
+ if ( !pBroker )
+ throw uno::RuntimeException();
+
+ uno::Reference< ::com::sun::star::ucb::XContentIdentifierFactory > xIdFac
+ = pBroker->getContentIdentifierFactoryInterface();
+ if ( !xIdFac.is() )
+ throw uno::RuntimeException();
+
+ uno::Reference< ::com::sun::star::ucb::XContentIdentifier > xIdFirst
+ = xIdFac->createContentIdentifier( aFirst.GetMainURL( INetURLObject::NO_DECODE ) );
+ uno::Reference< ::com::sun::star::ucb::XContentIdentifier > xIdSecond
+ = xIdFac->createContentIdentifier( aSecond.GetMainURL( INetURLObject::NO_DECODE ) );
+
+ if ( xIdFirst.is() && xIdSecond.is() )
+ {
+ uno::Reference< ::com::sun::star::ucb::XContentProvider > xProvider =
+ pBroker->getContentProviderInterface();
+ if ( !xProvider.is() )
+ throw uno::RuntimeException();
+ bResult = !xProvider->compareContentIds( xIdFirst, xIdSecond );
+ }
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( sal_False, "Can't compare URL's, treat as different!\n" );
+ }
+ }
+ }
+
+ return bResult;
+}
+
+BOOL SfxMedium::HasStorage_Impl() const
+{
+ return pImp->xStorage.is();
+}
+
+BOOL SfxMedium::IsOpen() const
+{
+ return pInStream || pOutStream || pImp->xStorage.is();
+}
+
+::rtl::OUString SfxMedium::CreateTempCopyWithExt( const ::rtl::OUString& aURL )
+{
+ ::rtl::OUString aResult;
+
+ if ( aURL.getLength() )
+ {
+ sal_Int32 nPrefixLen = aURL.lastIndexOf( '.' );
+ String aExt = ( nPrefixLen == -1 ) ? String() : String( aURL.copy( nPrefixLen ) );
+
+ ::rtl::OUString aNewTempFileURL = ::utl::TempFile( String(), &aExt ).GetURL();
+ if ( aNewTempFileURL.getLength() )
+ {
+ INetURLObject aSource( aURL );
+ INetURLObject aDest( aNewTempFileURL );
+ ::rtl::OUString aFileName = aDest.getName( INetURLObject::LAST_SEGMENT,
+ true,
+ INetURLObject::DECODE_WITH_CHARSET );
+ if ( aFileName.getLength() && aDest.removeSegment() )
+ {
+ try
+ {
+ uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
+ ::ucbhelper::Content aTargetContent( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
+ ::ucbhelper::Content aSourceContent( aSource.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
+ if ( aTargetContent.transferContent( aSourceContent,
+ ::ucbhelper::InsertOperation_COPY,
+ aFileName,
+ NameClash::OVERWRITE ) )
+ {
+ // Success
+ aResult = aNewTempFileURL;
+ }
+ }
+ catch( uno::Exception& )
+ {}
+ }
+ }
+ }
+
+ return aResult;
+}
+
+sal_Bool SfxMedium::CallApproveHandler( const uno::Reference< task::XInteractionHandler >& xHandler, uno::Any aRequest, sal_Bool bAllowAbort )
+{
+ sal_Bool bResult = sal_False;
+
+ if ( xHandler.is() )
+ {
+ try
+ {
+ uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( bAllowAbort ? 2 : 1 );
+
+ ::rtl::Reference< ::framework::ContinuationApprove > pApprove( new ::framework::ContinuationApprove() );
+ aContinuations[ 0 ] = pApprove.get();
+
+ if ( bAllowAbort )
+ {
+ ::rtl::Reference< ::framework::ContinuationAbort > pAbort( new ::framework::ContinuationAbort() );
+ aContinuations[ 1 ] = pAbort.get();
+ }
+
+ uno::Reference< task::XInteractionRequest > xRequest( new ::framework::InteractionRequest( aRequest, aContinuations ) );
+ xHandler->handle( xRequest );
+
+ bResult = pApprove->isSelected();
+ }
+ catch( const Exception& )
+ {
+ }
+ }
+
+ return bResult;
+}
+
+::rtl::OUString SfxMedium::SwitchDocumentToTempFile()
+{
+ // the method returns empty string in case of failure
+ ::rtl::OUString aResult;
+ ::rtl::OUString aOrigURL = aLogicName;
+
+ if ( aOrigURL.getLength() )
+ {
+ sal_Int32 nPrefixLen = aOrigURL.lastIndexOf( '.' );
+ String aExt = ( nPrefixLen == -1 ) ? String() : String( aOrigURL.copy( nPrefixLen ) );
+ ::rtl::OUString aNewURL = ::utl::TempFile( String(), &aExt ).GetURL();
+
+ // TODO/LATER: In future the aLogicName should be set to shared folder URL
+ // and a temporary file should be created. Transport_Impl should be impossible then.
+ if ( aNewURL.getLength() )
+ {
+ uno::Reference< embed::XStorage > xStorage = GetStorage();
+ uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
+
+ if ( xOptStorage.is() )
+ {
+ // TODO/LATER: reuse the pImp->pTempFile if it already exists
+ CanDisposeStorage_Impl( sal_False );
+ Close();
+ SetPhysicalName_Impl( String() );
+ SetName( aNewURL );
+
+ // remove the readonly state
+ sal_Bool bWasReadonly = sal_False;
+ nStorOpenMode = SFX_STREAM_READWRITE;
+ SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, FALSE );
+ if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
+ bWasReadonly = sal_True;
+ GetItemSet()->ClearItem( SID_DOC_READONLY );
+
+ GetMedium_Impl();
+ LockOrigFileOnDemand( sal_False, sal_False );
+ CreateTempFile( sal_True );
+ GetMedium_Impl();
+
+ if ( pImp->xStream.is() )
+ {
+ try
+ {
+ xOptStorage->writeAndAttachToStream( pImp->xStream );
+ pImp->xStorage = xStorage;
+ aResult = aNewURL;
+ }
+ catch( uno::Exception& )
+ {}
+ }
+
+ if ( !aResult.getLength() )
+ {
+ Close();
+ SetPhysicalName_Impl( String() );
+ SetName( aOrigURL );
+ if ( bWasReadonly )
+ {
+ // set the readonly state back
+ nStorOpenMode = SFX_STREAM_READONLY;
+ GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY, sal_True));
+ }
+ GetMedium_Impl();
+ pImp->xStorage = xStorage;
+ }
+ }
+ }
+ }
+
+ return aResult;
+}
+
+sal_Bool SfxMedium::SwitchDocumentToFile( ::rtl::OUString aURL )
+{
+ // the method is only for storage based documents
+ sal_Bool bResult = sal_False;
+ ::rtl::OUString aOrigURL = aLogicName;
+
+ if ( aURL.getLength() && aOrigURL.getLength() )
+ {
+ uno::Reference< embed::XStorage > xStorage = GetStorage();
+ uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
+
+ if ( xOptStorage.is() )
+ {
+ // TODO/LATER: reuse the pImp->pTempFile if it already exists
+ CanDisposeStorage_Impl( sal_False );
+ Close();
+ SetPhysicalName_Impl( String() );
+ SetName( aURL );
+
+ // open the temporary file based document
+ GetMedium_Impl();
+ LockOrigFileOnDemand( sal_False, sal_False );
+ CreateTempFile( sal_True );
+ GetMedium_Impl();
+
+ if ( pImp->xStream.is() )
+ {
+ try
+ {
+ uno::Reference< io::XTruncate > xTruncate( pImp->xStream, uno::UNO_QUERY_THROW );
+ if ( xTruncate.is() )
+ xTruncate->truncate();
+
+ xOptStorage->writeAndAttachToStream( pImp->xStream );
+ pImp->xStorage = xStorage;
+ bResult = sal_True;
+ }
+ catch( uno::Exception& )
+ {}
+ }
+
+ if ( !bResult )
+ {
+ Close();
+ SetPhysicalName_Impl( String() );
+ SetName( aOrigURL );
+ GetMedium_Impl();
+ pImp->xStorage = xStorage;
+ }
+ }
+ }
+
+ return bResult;
+}
+