| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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/ucb/Lock.hpp> |
| #include <com/sun/star/ucb/InteractiveLockingLockNotAvailableException.hpp> |
| #include <com/sun/star/ucb/InteractiveLockingLockedException.hpp> |
| #include <com/sun/star/ucb/InteractiveNetworkReadException.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 <comphelper/interaction.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 <comphelper/docpasswordhelper.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 "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 "sfx2/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; |
| |
| ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xCredentialInteraction; |
| |
| sal_Bool m_bRemoveBackup; |
| ::rtl::OUString m_aBackupURL; |
| |
| // the following member is changed and makes sense 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() |
| { |
| ::rtl::OUString aScheme = INetURLObject::GetScheme( GetURLObject().GetProtocol() ); |
| sal_Bool bIsWebDAV = ( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) || |
| aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) ); |
| return ( !IsReadOnly() && |
| ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) || bIsWebDAV ) ); |
| } |
| |
| //------------------------------------------------------------------ |
| 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( sal_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 sal_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 = sal_True; |
| } |
| else if ( GetInStream() ) |
| { |
| pImp->bIsStorage = SotStorage::IsStorageFile( pInStream ) && !SotStorage::IsOLEStorage( pInStream ); |
| if ( !pInStream->GetError() && !pImp->bIsStorage ) |
| bTriedStorage = sal_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::SetEncryptionDataToStorage_Impl() |
| { |
| // in case media-descriptor contains password it should be used on opening |
| if ( pImp->xStorage.is() && pSet ) |
| { |
| uno::Sequence< beans::NamedValue > aEncryptionData; |
| if ( GetEncryptionData_Impl( pSet, aEncryptionData ) ) |
| { |
| // replace the password with encryption data |
| pSet->ClearItem( SID_PASSWORD ); |
| pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) ); |
| |
| try |
| { |
| ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( pImp->xStorage, aEncryptionData ); |
| } |
| 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 ) ) ); |
| } |
| } |
| } |
| } |
| |
| //->i126305 ----------------------------------------------------------------- |
| //for the time being the aData holds a single OUString, the owner of the lock |
| sal_Int8 SfxMedium::ShowLockedWebDAVDocumentDialog( const uno::Sequence< ::rtl::OUString >& aData, sal_Bool bIsLoading ) |
| { |
| 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 ) |
| { |
| ::rtl::OUString aDocumentURL = GetURLObject().GetLastName(); |
| ::rtl::OUString aInfo; |
| ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl; |
| |
| aInfo = aData[0]; |
| if(aData.getLength() > 1 && aData[1].getLength() > 0) |
| { |
| aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\n" ) ); |
| aInfo += aData[1]; |
| } |
| |
| 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() ) |
| { |
| // 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 |
| // means that a copy of the document should be opened |
| GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE, sal_True ) ); |
| } |
| else // if ( XSelected == aContinuations[1] ) |
| { |
| // 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; |
| } |
| //<-i126305 |
| |
| //------------------------------------------------------------------ |
| 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 successfully 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 successfully 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 |
| { |
| //->i126305 |
| // check if path scheme is http:// or https:// |
| ::rtl::OUString aScheme = INetURLObject::GetScheme(GetURLObject().GetProtocol()); |
| if( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) || |
| aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) ) |
| { |
| //so, this is webdav stuff... |
| Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler(); |
| 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() ) |
| { |
| |
| // 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; |
| do |
| { |
| if( !bResult ) |
| { |
| Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv; |
| uno::Reference< task::XInteractionHandler > xCHandler = GetAuthenticationInteractionHandler(); |
| xComEnv = new ::ucbhelper::CommandEnvironment( xCHandler, |
| Reference< ::com::sun::star::ucb::XProgressHandler >() ); |
| ::ucbhelper::Content aContentToLock( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xComEnv); |
| rtl::OUString aOwner; |
| try { |
| aContentToLock.lock(); |
| bResult = sal_True; |
| } |
| catch( ucb::InteractiveLockingLockNotAvailableException ) |
| { |
| // signalled when the lock can not be done because the method is known but not allowed on the resource |
| // the resource is still available, can be worked upon, at your risk |
| // so 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( ucb::InteractiveLockingLockedException& e ) |
| { |
| // here get the lock owner currently active |
| aOwner = e.Owner; |
| rtl::OUString aExtendedError; |
| |
| if ( !bResult && !bNoUI ) |
| { |
| uno::Sequence< ::rtl::OUString > aData( 2 ); |
| |
| aData[0] = aOwner; |
| aData[1] = aExtendedError; |
| bUIStatus = ShowLockedWebDAVDocumentDialog( aData, bLoading ); |
| if ( bUIStatus == LOCK_UI_SUCCEEDED ) |
| { |
| // take the ownership over the lock file, accept the current lock (already there) |
| bResult = sal_True; |
| } |
| } |
| } |
| } |
| } while( !bResult && bUIStatus == LOCK_UI_TRY ); |
| } |
| |
| 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, sal_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 ) ); |
| } |
| |
| pImp->m_bLocked = bResult; |
| } |
| else |
| { |
| // this is neither file URL nor WebDAV, check whether the file is readonly |
| bResult = !bContentReadonly; |
| } |
| //<-i126305 |
| } |
| } |
| } |
| |
| 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, sal_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() ) |
| { |
| SetEncryptionDataToStorage_Impl(); |
| GetVersionList(); |
| } |
| |
| SFX_ITEMSET_ARG( pSet, pVersion, SfxInt16Item, SID_VERSION, sal_False); |
| |
| sal_Bool bResetStorage = sal_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 = sal_True; |
| } |
| } |
| else |
| bResetStorage = sal_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() : sal_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 sense 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 sense 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, sal_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 |
| { |
| //add acheck for protocol, to see if it's http or https then add |
| //the interecation handler to be used by the authentication dialog |
| ::rtl::OUString aScheme = INetURLObject::GetScheme(GetURLObject().GetProtocol()); |
| if( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) || |
| aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) ) |
| { |
| aMedium[comphelper::MediaDescriptor::PROP_AUTHENTICATIONHANDLER()] <<= GetAuthenticationInteractionHandler(); |
| } |
| 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 = sal_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, sal_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( sal_Bool bUse ) |
| { |
| pImp->bAllowDefaultIntHdl = bUse; |
| } |
| |
| //------------------------------------------------------------------ |
| |
| ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > |
| SfxMedium::GetAuthenticationInteractionHandler() |
| { |
| // 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; |
| } |
| |
| // otherwise return cached default handler ... if it exist. |
| if ( pImp->xCredentialInteraction.is() ) |
| return pImp->xCredentialInteraction; |
| |
| // create default handler and cache it! |
| ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); |
| if ( xFactory.is() ) |
| { |
| pImp->xCredentialInteraction = ::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->xCredentialInteraction; |
| } |
| |
| return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >(); |
| } |
| |
| //------------------------------------------------------------------ |
| |
| ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > |
| SfxMedium::GetInteractionHandler() |
| { |
| // if interaction isn't 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 isn't allowed explicitly ... return empty reference! |
| if ( !pImp->bAllowDefaultIntHdl ) |
| return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >(); |
| |
| // otherwise 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; |
| } |
| |
| //------------------------------------------------------------------ |
| |
| sal_uInt32 SfxMedium::CreatePasswordToModifyHash( const ::rtl::OUString& aPasswd, sal_Bool bWriter ) |
| { |
| sal_uInt32 nHash = 0; |
| |
| if ( aPasswd.getLength() ) |
| { |
| if ( bWriter ) |
| { |
| nHash = ::comphelper::DocPasswordHelper::GetWordHashAsUINT32( aPasswd ); |
| } |
| else |
| { |
| rtl_TextEncoding nEncoding = RTL_TEXTENCODING_UTF8; |
| |
| // if the MS-filter should be used |
| // use the inconsistent algorithm to find the encoding specified by MS |
| nEncoding = osl_getThreadTextEncoding(); |
| switch( nEncoding ) |
| { |
| case RTL_TEXTENCODING_ISO_8859_15: |
| case RTL_TEXTENCODING_MS_874: |
| case RTL_TEXTENCODING_MS_1250: |
| case RTL_TEXTENCODING_MS_1251: |
| case RTL_TEXTENCODING_MS_1252: |
| case RTL_TEXTENCODING_MS_1253: |
| case RTL_TEXTENCODING_MS_1254: |
| case RTL_TEXTENCODING_MS_1255: |
| case RTL_TEXTENCODING_MS_1256: |
| case RTL_TEXTENCODING_MS_1257: |
| case RTL_TEXTENCODING_MS_1258: |
| case RTL_TEXTENCODING_SHIFT_JIS: |
| case RTL_TEXTENCODING_GB_2312: |
| case RTL_TEXTENCODING_BIG5: |
| // in case the system uses an encoding from the list above, it should be used |
| break; |
| |
| default: |
| // in case other encoding is used, use one of the encodings from the list |
| nEncoding = RTL_TEXTENCODING_MS_1250; |
| break; |
| } |
| |
| nHash = ::comphelper::DocPasswordHelper::GetXLHashAsUINT16( aPasswd, nEncoding ); |
| } |
| } |
| |
| return nHash; |
| } |
| |
| //------------------------------------------------------------------ |
| |
| 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( sal_True ); |
| } |
| else if ( pStream && pStream == pOutStream ) |
| { |
| pOutStream = NULL; |
| aStorage->SetDeleteStream( sal_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( sal_True ); |
| } |
| else if ( pStream && pStream == pOutStream ) |
| { |
| pOutStream = NULL; |
| aStorage->SetDeleteStream( sal_True ); |
| } */ |
| |
| CloseStorage(); |
| } |
| |
| CloseAndReleaseStreams_Impl(); |
| |
| UnlockFile( sal_True ); |
| } |
| |
| void SfxMedium::UnlockFile( sal_Bool bReleaseLockStream ) |
| { |
| //->i126305 |
| //check if the file is local |
| if ( ::utl::LocalFileHelper::IsLocalFile( aLogicName ) ) |
| { |
| //<-i126305 |
| 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& ) |
| {} |
| } |
| //->i126305 |
| } |
| else |
| { |
| //not local, check if webdav |
| ::rtl::OUString aScheme = INetURLObject::GetScheme(GetURLObject().GetProtocol()); |
| if( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) || |
| aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) ) |
| { |
| if ( pImp->m_bLocked ) |
| { |
| // an interaction handler should be used for authentication |
| try { |
| Reference< ::com::sun::star::task::XInteractionHandler > xHandler = GetAuthenticationInteractionHandler(); |
| Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv; |
| xComEnv = new ::ucbhelper::CommandEnvironment( xHandler, |
| Reference< ::com::sun::star::ucb::XProgressHandler >() ); |
| ::ucbhelper::Content aContentToUnlock( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xComEnv); |
| pImp->m_bLocked = sal_False; |
| aContentToUnlock.unlock(); |
| } |
| catch (ucb::InteractiveNetworkReadException& e) |
| { |
| //signalled when this resource can not be unlocked, for whatever reason |
| } |
| catch( uno::Exception& ) |
| {} |
| } |
| } |
| } |
| //<-i126305 |
| } |
| |
| 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 = sal_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() |
| { |
| sal_Bool bUseInteractionHandler = pImp->bUseInteractionHandler; |
| pImp->bUseInteractionHandler = sal_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 |
| sal_Bool bUseInteractionHandler = pImp->bUseInteractionHandler; |
| pImp->bUseInteractionHandler = sal_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, sal_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" ); |
| } |
| } |
| } |
| |
| sal_Bool bReadOnly = sal_False; |
| SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False ); |
| if ( pReadOnlyItem && pReadOnlyItem->GetValue() ) |
| bReadOnly = sal_True; |
| |
| SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False ); |
| if (!pFileNameItem) throw uno::RuntimeException(); |
| aLogicName = pFileNameItem->GetValue(); |
| nStorOpenMode = bReadOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE; |
| bDirect = sal_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 = sal_False; |
| |
| // always take BaseURL first, could be overwritten by ItemSet |
| GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) ); |
| if ( p ) |
| GetItemSet()->Put( *p ); |
| } |
| |
| SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const String& rBaseURL, const String& rTypeName, const SfxItemSet* p, sal_Bool bRootP ) |
| : IMPL_CTOR( bRootP, 0 ), // bRoot, pURLObj |
| pSet(0), |
| pImp( new SfxMedium_Impl( this )) |
| { |
| pFilter = SFX_APP()->GetFilterMatcher().GetFilter4EA( rTypeName ); |
| DBG_ASSERT( pFilter, "No Filter for storage found!" ); |
| |
| Init_Impl(); |
| pImp->xStorage = rStor; |
| pImp->bDisposeStorage = sal_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. Otherwise maybe StyleSheets inside a html file will not 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 = sal_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] > ( sal_uIntPtr ) 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 can't 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(); |
| } |
| |
| do |
| { |
| pImp->pTempFile = new ::utl::TempFile(); |
| if ( GetName().Equals( pImp->pTempFile->GetURL() ) ) |
| { |
| delete pImp->pTempFile; |
| pImp->pTempFile = NULL; |
| } |
| } while ( pImp->pTempFile == NULL ); |
| 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 = NULL; |
| } |
| |
| do |
| { |
| pImp->pTempFile = new ::utl::TempFile(); |
| if ( GetName().Equals( pImp->pTempFile->GetURL() ) ) |
| { |
| delete pImp->pTempFile; |
| pImp->pTempFile = NULL; |
| } |
| } while ( pImp->pTempFile == NULL ); |
| 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 = sal_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 = sal_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 = sal_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::HasStorage_Impl() const |
| { |
| return pImp->xStorage.is(); |
| } |
| |
| sal_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< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove ); |
| aContinuations[ 0 ] = pApprove.get(); |
| |
| if ( bAllowAbort ) |
| { |
| ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort( new ::comphelper::OInteractionAbort ); |
| aContinuations[ 1 ] = pAbort.get(); |
| } |
| |
| xHandler->handle(::framework::InteractionRequest::CreateRequest (aRequest,aContinuations)); |
| bResult = pApprove->wasSelected(); |
| } |
| 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, sal_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; |
| } |
| |