1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <sfx2/docfile.hxx>
30 #include "sfx2/signaturestate.hxx"
32 #include <uno/mapping.hxx>
33 #include <com/sun/star/task/XInteractionHandler.hpp>
34 #include <com/sun/star/uno/Reference.h>
35 #include <com/sun/star/ucb/XContent.hpp>
36 #include <com/sun/star/container/XChild.hpp>
37 #include <com/sun/star/document/XDocumentRevisionListPersistence.hpp>
38 #include <com/sun/star/document/LockedDocumentRequest.hpp>
39 #include <com/sun/star/document/OwnLockOnDocumentRequest.hpp>
40 #include <com/sun/star/document/LockedOnSavingRequest.hpp>
41 #include <com/sun/star/document/LockFileIgnoreRequest.hpp>
42 #include <com/sun/star/document/ChangedByOthersRequest.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/embed/XTransactedObject.hpp>
45 #include <com/sun/star/embed/ElementModes.hpp>
46 #include <com/sun/star/embed/UseBackupException.hpp>
47 #include <com/sun/star/embed/XOptimizedStorage.hpp>
48 #include <com/sun/star/ucb/InteractiveIOException.hpp>
49 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
50 #include <com/sun/star/ucb/CommandFailedException.hpp>
51 #include <com/sun/star/ucb/CommandAbortedException.hpp>
52 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
53 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
54 #include <com/sun/star/ucb/XContentProvider.hpp>
55 #include <com/sun/star/ucb/XProgressHandler.hpp>
56 #include <com/sun/star/ucb/XCommandInfo.hpp>
57 #include <com/sun/star/util/XArchiver.hpp>
58 #include <com/sun/star/io/XOutputStream.hpp>
59 #include <com/sun/star/io/XInputStream.hpp>
60 #include <com/sun/star/io/XTruncate.hpp>
61 #include <com/sun/star/io/XStreamListener.hpp>
62 #include <com/sun/star/io/XSeekable.hpp>
63 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
64 #include <com/sun/star/lang/XInitialization.hpp>
65 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
66 #include <com/sun/star/ucb/NameClash.hpp>
67 #include <com/sun/star/ucb/TransferInfo.hpp>
68 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
69 #include <com/sun/star/ucb/OpenMode.hpp>
70 #include <com/sun/star/logging/XSimpleLogRing.hpp>
71 #include <cppuhelper/implbase1.hxx>
72 #include <com/sun/star/beans/PropertyValue.hpp>
73 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
74 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
75 #include <tools/urlobj.hxx>
76 #include <unotools/tempfile.hxx>
77 #include <comphelper/processfactory.hxx>
78 #include <comphelper/componentcontext.hxx>
79 #include <comphelper/interaction.hxx>
80 #include <framework/interaction.hxx>
81 #include <unotools/streamhelper.hxx>
82 #include <unotools/localedatawrapper.hxx>
83 #include <vcl/msgbox.hxx>
84 #include <svl/stritem.hxx>
85 #include <svl/eitem.hxx>
86 #include <svl/lckbitem.hxx>
87 #include <svtools/sfxecode.hxx>
88 #include <svl/itemset.hxx>
89 #include <svl/intitem.hxx>
90 #include <svtools/svparser.hxx> // SvKeyValue
91 #include <cppuhelper/weakref.hxx>
92 #include <svl/svstdarr.hxx>
94 #include <unotools/streamwrap.hxx>
96 #include <rtl/logfile.hxx>
97 #include <osl/file.hxx>
99 using namespace ::com::sun::star
;
100 using namespace ::com::sun::star::uno
;
101 using namespace ::com::sun::star::ucb
;
102 using namespace ::com::sun::star::beans
;
103 using namespace ::com::sun::star::io
;
105 #include <comphelper/storagehelper.hxx>
106 #include <comphelper/mediadescriptor.hxx>
107 #include <comphelper/configurationhelper.hxx>
108 #include <comphelper/docpasswordhelper.hxx>
109 #include <tools/inetmime.hxx>
110 #include <unotools/ucblockbytes.hxx>
111 #include <unotools/pathoptions.hxx>
112 #include <svtools/asynclink.hxx>
113 #include <svl/inettype.hxx>
114 #include <ucbhelper/contentbroker.hxx>
115 #include <ucbhelper/commandenvironment.hxx>
116 #include <unotools/localfilehelper.hxx>
117 #include <unotools/ucbstreamhelper.hxx>
118 #include <unotools/ucbhelper.hxx>
119 #include <unotools/progresshandlerwrap.hxx>
120 #include <ucbhelper/content.hxx>
121 #include <ucbhelper/interactionrequest.hxx>
122 #include <sot/stg.hxx>
123 #include <unotools/saveopt.hxx>
124 #include <svl/documentlockfile.hxx>
126 #include "helper.hxx"
127 #include <sfx2/request.hxx> // SFX_ITEMSET_SET
128 #include <sfx2/app.hxx> // GetFilterMatcher
129 #include <sfx2/frame.hxx> // LoadTargetFrame
130 #include "fltfnc.hxx" // SfxFilterMatcher
131 #include <sfx2/docfilt.hxx> // SfxFilter
132 #include <sfx2/objsh.hxx> // CheckOpenMode
133 #include <sfx2/docfac.hxx> // GetFilterContainer
135 #include "openflag.hxx" // SFX_STREAM_READONLY etc.
136 #include "sfx2/sfxresid.hxx"
137 #include <sfx2/appuno.hxx>
138 #include "sfxacldetect.hxx"
139 #include "officecfg/Office/Common.hxx"
141 //==========================================================
144 static const sal_Int8 LOCK_UI_NOLOCK
= 0;
145 static const sal_Int8 LOCK_UI_SUCCEEDED
= 1;
146 static const sal_Int8 LOCK_UI_TRY
= 2;
148 //----------------------------------------------------------------
149 sal_Bool
IsSystemFileLockingUsed()
151 // check whether system file locking has been used, the default value is false
152 sal_Bool bUseSystemLock
= sal_False
;
156 uno::Reference
< uno::XInterface
> xCommonConfig
= ::comphelper::ConfigurationHelper::openConfig(
157 ::comphelper::getProcessServiceFactory(),
158 ::rtl::OUString( "/org.openoffice.Office.Common" ),
159 ::comphelper::ConfigurationHelper::E_STANDARD
);
160 if ( !xCommonConfig
.is() )
161 throw uno::RuntimeException();
163 ::comphelper::ConfigurationHelper::readRelativeKey(
165 ::rtl::OUString( "Misc/" ),
166 ::rtl::OUString( "UseDocumentSystemFileLocking" ) ) >>= bUseSystemLock
;
168 catch( const uno::Exception
& )
172 return bUseSystemLock
;
175 //----------------------------------------------------------------
176 sal_Bool
IsOOoLockFileUsed()
178 // check whether system file locking has been used, the default value is false
179 sal_Bool bOOoLockFileUsed
= sal_False
;
183 uno::Reference
< uno::XInterface
> xCommonConfig
= ::comphelper::ConfigurationHelper::openConfig(
184 ::comphelper::getProcessServiceFactory(),
185 ::rtl::OUString( "/org.openoffice.Office.Common" ),
186 ::comphelper::ConfigurationHelper::E_STANDARD
);
187 if ( !xCommonConfig
.is() )
188 throw uno::RuntimeException();
190 ::comphelper::ConfigurationHelper::readRelativeKey(
192 ::rtl::OUString( "Misc/" ),
193 ::rtl::OUString( "UseDocumentOOoLockFile" ) ) >>= bOOoLockFileUsed
;
195 catch( const uno::Exception
& )
199 return bOOoLockFileUsed
;
204 return officecfg::Office::Common::Misc::UseLocking::get();
207 } // anonymous namespace
208 //==========================================================
211 //----------------------------------------------------------------
212 class SfxMediumHandler_Impl
: public ::cppu::WeakImplHelper1
< com::sun::star::task::XInteractionHandler
>
214 com::sun::star::uno::Reference
< com::sun::star::task::XInteractionHandler
> m_xInter
;
217 virtual void SAL_CALL
handle( const com::sun::star::uno::Reference
< com::sun::star::task::XInteractionRequest
>& xRequest
)
218 throw( com::sun::star::uno::RuntimeException
);
220 SfxMediumHandler_Impl( com::sun::star::uno::Reference
< com::sun::star::task::XInteractionHandler
> xInteraction
)
221 : m_xInter( xInteraction
)
224 ~SfxMediumHandler_Impl();
227 //----------------------------------------------------------------
228 SfxMediumHandler_Impl::~SfxMediumHandler_Impl()
232 //----------------------------------------------------------------
233 void SAL_CALL
SfxMediumHandler_Impl::handle( const com::sun::star::uno::Reference
< com::sun::star::task::XInteractionRequest
>& xRequest
)
234 throw( com::sun::star::uno::RuntimeException
)
239 com::sun::star::uno::Any aRequest
= xRequest
->getRequest();
240 com::sun::star::ucb::InteractiveIOException aIoException
;
241 com::sun::star::ucb::UnsupportedDataSinkException aSinkException
;
242 if ( (aRequest
>>= aIoException
) && ( aIoException
.Code
== IOErrorCode_ACCESS_DENIED
|| aIoException
.Code
== IOErrorCode_LOCKING_VIOLATION
) )
245 if ( aRequest
>>= aSinkException
)
248 m_xInter
->handle( xRequest
);
251 //----------------------------------------------------------------
255 ::ucbhelper::Content aContent
;
256 sal_Bool bUpdatePickList
: 1;
257 sal_Bool bIsTemp
: 1;
258 sal_Bool bForceSynchron
: 1;
259 sal_Bool bDownloadDone
: 1;
260 sal_Bool bDontCallDoneLinkOnSharingError
: 1;
261 sal_Bool bIsStorage
: 1;
262 sal_Bool bUseInteractionHandler
: 1;
263 sal_Bool bAllowDefaultIntHdl
: 1;
264 sal_Bool bIsCharsetInitialized
: 1;
265 sal_Bool bDisposeStorage
: 1;
266 sal_Bool bStorageBasedOnInStream
: 1;
267 sal_Bool m_bSalvageMode
: 1;
268 sal_Bool m_bVersionsAlreadyLoaded
: 1;
269 sal_Bool m_bLocked
: 1;
270 sal_Bool m_bGotDateTime
: 1;
272 uno::Reference
< embed::XStorage
> xStorage
;
274 SfxMedium
* pAntiImpl
;
278 const SfxFilter
* pOrigFilter
;
280 String aPreRedirectionURL
;
282 DateTime aExpireTime
;
283 SfxFrameWeak wLoadTargetFrame
;
284 SvKeyValueIteratorRef xAttributes
;
286 svtools::AsynchronLink aDoneLink
;
287 svtools::AsynchronLink aAvailableLink
;
289 uno::Sequence
< util::RevisionTag
> aVersions
;
291 ::utl::TempFile
* pTempFile
;
293 uno::Reference
< embed::XStorage
> m_xZipStorage
;
294 Reference
< XInputStream
> xInputStream
;
295 Reference
< XStream
> xStream
;
297 uno::Reference
< io::XStream
> m_xLockingStream
;
299 sal_uInt32 nLastStorageError
;
300 ::rtl::OUString aCharset
;
302 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
> xInteraction
;
304 sal_Bool m_bRemoveBackup
;
305 ::rtl::OUString m_aBackupURL
;
307 // the following member is changed and makes sence only during saving
308 // TODO/LATER: in future the signature state should be controlled by the medium not by the document
309 // in this case the member will hold this information
310 sal_uInt16 m_nSignatureState
;
312 util::DateTime m_aDateTime
;
314 uno::Reference
< logging::XSimpleLogRing
> m_xLogRing
;
316 bool m_originallyReadOnly
;
318 SfxMedium_Impl( SfxMedium
* pAntiImplP
);
322 //------------------------------------------------------------------
323 SfxMedium_Impl::SfxMedium_Impl( SfxMedium
* pAntiImplP
)
324 : bUpdatePickList(sal_True
),
325 bIsTemp( sal_False
),
326 bForceSynchron( sal_False
),
327 bDownloadDone( sal_True
),
328 bDontCallDoneLinkOnSharingError( sal_False
),
329 bIsStorage( sal_False
),
330 bUseInteractionHandler( sal_True
),
331 bAllowDefaultIntHdl( sal_False
),
332 bIsCharsetInitialized( sal_False
),
333 bStorageBasedOnInStream( sal_False
),
334 m_bSalvageMode( sal_False
),
335 m_bVersionsAlreadyLoaded( sal_False
),
336 m_bLocked( sal_False
),
337 m_bGotDateTime( sal_False
),
338 pAntiImpl( pAntiImplP
),
341 aExpireTime( Date( Date::SYSTEM
) + 10, Time( Time::SYSTEM
) ),
343 nLastStorageError( 0 ),
344 m_bRemoveBackup( sal_False
),
345 m_nSignatureState( SIGNATURESTATE_NOSIGNATURES
),
346 m_originallyReadOnly(false)
348 aDoneLink
.CreateMutex();
351 //------------------------------------------------------------------
352 SfxMedium_Impl::~SfxMedium_Impl()
355 aDoneLink
.ClearPendingCall();
356 aAvailableLink
.ClearPendingCall();
362 //================================================================
364 #define IMPL_CTOR(rootVal,URLVal) \
365 eError( SVSTREAM_OK ), \
368 bSetFilter( sal_False ), \
369 bTriedStorage( sal_False ), \
371 nStorOpenMode( SFX_STREAM_READWRITE ), \
376 //------------------------------------------------------------------
377 void SfxMedium::ResetError()
379 eError
= SVSTREAM_OK
;
381 pInStream
->ResetError();
383 pOutStream
->ResetError();
386 //------------------------------------------------------------------
387 sal_uInt32
SfxMedium::GetLastStorageCreationState()
389 return pImp
->nLastStorageError
;
392 //------------------------------------------------------------------
393 void SfxMedium::AddLog( const ::rtl::OUString
& aMessage
)
395 if ( !pImp
->m_xLogRing
.is() )
399 ::comphelper::ComponentContext
aContext( ::comphelper::getProcessServiceFactory() );
401 pImp
->m_xLogRing
.set( aContext
.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), UNO_QUERY_THROW
);
403 catch( const uno::Exception
& )
407 if ( pImp
->m_xLogRing
.is() )
408 pImp
->m_xLogRing
->logString( aMessage
);
411 //------------------------------------------------------------------
412 void SfxMedium::SetError( sal_uInt32 nError
, const ::rtl::OUString
& aLogMessage
)
415 if ( eError
!= ERRCODE_NONE
&& !aLogMessage
.isEmpty() )
416 AddLog( aLogMessage
);
419 //------------------------------------------------------------------
420 sal_uInt32
SfxMedium::GetErrorCode() const
422 sal_uInt32 lError
=eError
;
423 if(!lError
&& pInStream
)
424 lError
=pInStream
->GetErrorCode();
425 if(!lError
&& pOutStream
)
426 lError
=pOutStream
->GetErrorCode();
430 //------------------------------------------------------------------
431 void SfxMedium::CheckFileDate( const util::DateTime
& aInitDate
)
433 GetInitFileDate( sal_True
);
434 if ( pImp
->m_aDateTime
.Seconds
!= aInitDate
.Seconds
435 || pImp
->m_aDateTime
.Minutes
!= aInitDate
.Minutes
436 || pImp
->m_aDateTime
.Hours
!= aInitDate
.Hours
437 || pImp
->m_aDateTime
.Day
!= aInitDate
.Day
438 || pImp
->m_aDateTime
.Month
!= aInitDate
.Month
439 || pImp
->m_aDateTime
.Year
!= aInitDate
.Year
)
441 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
447 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
448 document::ChangedByOthersRequest() ) );
449 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 3 );
450 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl
.get() );
451 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl
.get() );
452 xInteractionRequestImpl
->setContinuations( aContinuations
);
454 xHandler
->handle( xInteractionRequestImpl
.get() );
456 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xInteractionRequestImpl
->getSelection();
457 if ( uno::Reference
< task::XInteractionAbort
>( xSelected
.get(), uno::UNO_QUERY
).is() )
459 SetError( ERRCODE_ABORT
, ::rtl::OUString( OSL_LOG_PREFIX
) );
462 catch ( const uno::Exception
& )
468 //------------------------------------------------------------------
469 sal_Bool
SfxMedium::DocNeedsFileDateCheck()
471 return ( !IsReadOnly() && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) );
474 //------------------------------------------------------------------
475 util::DateTime
SfxMedium::GetInitFileDate( sal_Bool bIgnoreOldValue
)
477 if ( ( bIgnoreOldValue
|| !pImp
->m_bGotDateTime
) && aLogicName
.Len() )
481 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
482 ::ucbhelper::Content
aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
);
484 aContent
.getPropertyValue( ::rtl::OUString("DateModified" ) ) >>= pImp
->m_aDateTime
;
485 pImp
->m_bGotDateTime
= sal_True
;
487 catch ( const ::com::sun::star::uno::Exception
& )
492 return pImp
->m_aDateTime
;
495 //------------------------------------------------------------------
496 Reference
< XContent
> SfxMedium::GetContent() const
498 if ( !pImp
->aContent
.get().is() )
500 Reference
< ::com::sun::star::ucb::XContent
> xContent
;
501 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
503 SFX_ITEMSET_ARG( pSet
, pItem
, SfxUnoAnyItem
, SID_CONTENT
, sal_False
);
505 pItem
->GetValue() >>= xContent
;
511 pImp
->aContent
= ::ucbhelper::Content( xContent
, xEnv
);
513 catch ( const Exception
& )
519 // TODO: OSL_FAIL("SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
521 if ( !aName
.isEmpty() )
522 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aURL
);
523 else if ( aLogicName
.Len() )
524 aURL
= GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
525 if (!aURL
.isEmpty() )
526 ::ucbhelper::Content::create( aURL
, xEnv
, pImp
->aContent
);
530 return pImp
->aContent
.get();
533 //------------------------------------------------------------------
534 ::rtl::OUString
SfxMedium::GetBaseURL( bool bForSaving
)
536 ::rtl::OUString aBaseURL
;
537 const SfxStringItem
* pBaseURLItem
= static_cast<const SfxStringItem
*>( GetItemSet()->GetItem(SID_DOC_BASEURL
) );
539 aBaseURL
= pBaseURLItem
->GetValue();
540 else if ( GetContent().is() )
544 Any aAny
= pImp
->aContent
.getPropertyValue( ::rtl::OUString("BaseURI" ) );
547 catch ( const ::com::sun::star::uno::Exception
& )
551 if ( aBaseURL
.isEmpty() )
552 aBaseURL
= GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
558 sal_Bool bIsRemote
= IsRemote();
559 if( (bIsRemote
&& !aOpt
.IsSaveRelINet()) || (!bRemote
&& !aOpt
.IsSaveRelFSys()) )
560 return ::rtl::OUString();
566 //------------------------------------------------------------------
567 SvStream
* SfxMedium::GetInStream()
572 if ( pImp
->pTempFile
)
574 pInStream
= new SvFileStream( aName
, nStorOpenMode
);
576 eError
= pInStream
->GetError();
578 if( !eError
&& (nStorOpenMode
& STREAM_WRITE
)
579 && ! pInStream
->IsWritable() )
581 eError
= ERRCODE_IO_ACCESSDENIED
;
597 //------------------------------------------------------------------
598 void SfxMedium::CloseInStream()
600 CloseInStream_Impl();
603 void SfxMedium::CloseInStream_Impl()
605 // if there is a storage based on the InStream, we have to
606 // close the storage, too, because otherwise the storage
607 // would use an invalid ( deleted ) stream.
608 if ( pInStream
&& pImp
->xStorage
.is() )
610 if ( pImp
->bStorageBasedOnInStream
)
614 if ( pInStream
&& !GetContent().is() )
616 CreateTempFile( sal_True
);
620 DELETEZ( pInStream
);
622 pSet
->ClearItem( SID_INPUTSTREAM
);
624 CloseZipStorage_Impl();
625 pImp
->xInputStream
= uno::Reference
< io::XInputStream
>();
629 // output part of the stream is not used so the whole stream can be closed
630 // TODO/LATER: is it correct?
631 pImp
->xStream
= uno::Reference
< io::XStream
>();
633 pSet
->ClearItem( SID_STREAM
);
637 //------------------------------------------------------------------
638 SvStream
* SfxMedium::GetOutStream()
642 // Create a temp. file if there is none because we always
644 CreateTempFile( sal_False
);
646 if ( pImp
->pTempFile
)
648 pOutStream
= new SvFileStream( aName
, STREAM_STD_READWRITE
);
656 //------------------------------------------------------------------
657 sal_Bool
SfxMedium::CloseOutStream()
659 CloseOutStream_Impl();
663 sal_Bool
SfxMedium::CloseOutStream_Impl()
667 // if there is a storage based on the OutStream, we have to
668 // close the storage, too, because otherwise the storage
669 // would use an invalid ( deleted ) stream.
670 //TODO/MBA: how to deal with this?!
671 //maybe we need a new flag when the storage was created from the outstream
672 if ( pImp
->xStorage
.is() )
683 // input part of the stream is not used so the whole stream can be closed
684 // TODO/LATER: is it correct?
685 pImp
->xStream
= uno::Reference
< io::XStream
>();
687 pSet
->ClearItem( SID_STREAM
);
693 //------------------------------------------------------------------
694 const rtl::OUString
& SfxMedium::GetPhysicalName() const
696 if ( aName
.isEmpty() && aLogicName
.Len() )
697 (( SfxMedium
*)this)->CreateFileStream();
699 // return the name then
703 //------------------------------------------------------------------
704 void SfxMedium::CreateFileStream()
706 ForceSynchronStream_Impl( sal_True
);
710 CreateTempFile( sal_False
);
711 pImp
->bIsTemp
= sal_True
;
712 CloseInStream_Impl();
716 //------------------------------------------------------------------
717 sal_Bool
SfxMedium::Commit()
719 if( pImp
->xStorage
.is() )
720 StorageCommit_Impl();
721 else if( pOutStream
)
726 if ( GetError() == SVSTREAM_OK
)
728 // does something only in case there is a temporary file ( means aName points to different location than aLogicName )
732 sal_Bool bResult
= ( GetError() == SVSTREAM_OK
);
734 if ( bResult
&& DocNeedsFileDateCheck() )
735 GetInitFileDate( sal_True
);
737 // remove truncation mode from the flags
738 nStorOpenMode
&= (~STREAM_TRUNC
);
742 //------------------------------------------------------------------
743 sal_Bool
SfxMedium::IsStorage()
745 if ( pImp
->xStorage
.is() )
749 return pImp
->bIsStorage
;
751 if ( pImp
->pTempFile
)
754 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aURL
) )
756 OSL_FAIL("Physical name not convertable!");
758 pImp
->bIsStorage
= SotStorage::IsStorageFile( aURL
) && !SotStorage::IsOLEStorage( aURL
);
759 if ( !pImp
->bIsStorage
)
760 bTriedStorage
= sal_True
;
762 else if ( GetInStream() )
764 pImp
->bIsStorage
= SotStorage::IsStorageFile( pInStream
) && !SotStorage::IsOLEStorage( pInStream
);
765 if ( !pInStream
->GetError() && !pImp
->bIsStorage
)
766 bTriedStorage
= sal_True
;
769 return pImp
->bIsStorage
;
772 //------------------------------------------------------------------
773 sal_Bool
SfxMedium::IsPreview_Impl()
775 sal_Bool bPreview
= sal_False
;
776 SFX_ITEMSET_ARG( GetItemSet(), pPreview
, SfxBoolItem
, SID_PREVIEW
, sal_False
);
778 bPreview
= pPreview
->GetValue();
781 SFX_ITEMSET_ARG( GetItemSet(), pFlags
, SfxStringItem
, SID_OPTIONS
, sal_False
);
784 String aFileFlags
= pFlags
->GetValue();
785 aFileFlags
.ToUpperAscii();
786 if ( STRING_NOTFOUND
!= aFileFlags
.Search( 'B' ) )
794 //------------------------------------------------------------------
795 void SfxMedium::StorageBackup_Impl()
797 ::ucbhelper::Content aOriginalContent
;
798 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
800 sal_Bool bBasedOnOriginalFile
= ( !pImp
->pTempFile
&& !( aLogicName
.Len() && pImp
->m_bSalvageMode
)
801 && !GetURLObject().GetMainURL( INetURLObject::NO_DECODE
).isEmpty()
802 && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
803 && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) );
805 if ( bBasedOnOriginalFile
&& pImp
->m_aBackupURL
.isEmpty()
806 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, aOriginalContent
) )
808 DoInternalBackup_Impl( aOriginalContent
);
809 if( pImp
->m_aBackupURL
.isEmpty() )
810 SetError( ERRCODE_SFX_CANTCREATEBACKUP
, ::rtl::OUString( OSL_LOG_PREFIX
) );
814 //------------------------------------------------------------------
815 ::rtl::OUString
SfxMedium::GetBackup_Impl()
817 if ( pImp
->m_aBackupURL
.isEmpty() )
818 StorageBackup_Impl();
820 return pImp
->m_aBackupURL
;
823 //------------------------------------------------------------------
824 uno::Reference
< embed::XStorage
> SfxMedium::GetOutputStorage()
827 return uno::Reference
< embed::XStorage
>();
829 // if the medium was constructed with a Storage: use this one, not a temp. storage
830 // if a temporary storage already exists: use it
831 if ( pImp
->xStorage
.is() && ( !aLogicName
.Len() || pImp
->pTempFile
) )
832 return pImp
->xStorage
;
834 // if necessary close stream that was used for reading
835 if ( pInStream
&& !pInStream
->IsWritable() )
838 DBG_ASSERT( !pOutStream
, "OutStream in a readonly Medium?!" );
840 // TODO/LATER: The current solution is to store the document temporary and then copy it to the target location;
841 // in future it should be stored directly and then copied to the temporary location, since in this case no
842 // file attributes have to be preserved and system copying mechanics could be used instead of streaming.
843 CreateTempFileNoCopy();
848 //------------------------------------------------------------------
849 void SfxMedium::SetEncryptionDataToStorage_Impl()
851 // in case media-descriptor contains password it should be used on opening
852 if ( pImp
->xStorage
.is() && pSet
)
854 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
855 if ( GetEncryptionData_Impl( pSet
, aEncryptionData
) )
857 // replace the password with encryption data
858 pSet
->ClearItem( SID_PASSWORD
);
859 pSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
863 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( pImp
->xStorage
, aEncryptionData
);
865 catch( const uno::Exception
& )
867 OSL_FAIL( "It must be possible to set a common password for the storage" );
868 // TODO/LATER: set the error code in case of problem
869 // SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( OSL_LOG_PREFIX ) );
875 //------------------------------------------------------------------
876 sal_Int8
SfxMedium::ShowLockedDocumentDialog( const uno::Sequence
< ::rtl::OUString
>& aData
, sal_Bool bIsLoading
, sal_Bool bOwnLock
)
878 sal_Int8 nResult
= LOCK_UI_NOLOCK
;
880 // show the interaction regarding the document opening
881 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
883 if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler
.is() && ( bIsLoading
|| bOwnLock
) )
885 ::rtl::OUString aDocumentURL
= GetURLObject().GetLastName();
886 ::rtl::OUString aInfo
;
887 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xInteractionRequestImpl
;
891 if ( aData
.getLength() > LOCKFILE_EDITTIME_ID
)
892 aInfo
= aData
[LOCKFILE_EDITTIME_ID
];
894 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
895 document::OwnLockOnDocumentRequest( ::rtl::OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
, !bIsLoading
) ) );
899 if ( aData
.getLength() > LOCKFILE_EDITTIME_ID
)
901 if ( !aData
[LOCKFILE_OOOUSERNAME_ID
].isEmpty() )
902 aInfo
= aData
[LOCKFILE_OOOUSERNAME_ID
];
904 aInfo
= aData
[LOCKFILE_SYSUSERNAME_ID
];
906 if ( !aInfo
.isEmpty() && !aData
[LOCKFILE_EDITTIME_ID
].isEmpty() )
908 aInfo
+= ::rtl::OUString( " ( " );
909 aInfo
+= aData
[LOCKFILE_EDITTIME_ID
];
910 aInfo
+= ::rtl::OUString( " )" );
916 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
917 document::LockedDocumentRequest( ::rtl::OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
) ) );
921 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
922 document::LockedOnSavingRequest( ::rtl::OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
) ) );
927 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 3 );
928 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl
.get() );
929 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl
.get() );
930 aContinuations
[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl
.get() );
931 xInteractionRequestImpl
->setContinuations( aContinuations
);
933 xHandler
->handle( xInteractionRequestImpl
.get() );
935 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xInteractionRequestImpl
->getSelection();
936 if ( uno::Reference
< task::XInteractionAbort
>( xSelected
.get(), uno::UNO_QUERY
).is() )
938 SetError( ERRCODE_ABORT
, ::rtl::OUString( OSL_LOG_PREFIX
) );
940 else if ( uno::Reference
< task::XInteractionDisapprove
>( xSelected
.get(), uno::UNO_QUERY
).is() )
942 // own lock on loading, user has selected to ignore the lock
943 // own lock on saving, user has selected to ignore the lock
944 // alien lock on loading, user has selected to edit a copy of document
945 // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
946 if ( bIsLoading
&& !bOwnLock
)
948 // means that a copy of the document should be opened
949 GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE
, sal_True
) );
952 nResult
= LOCK_UI_SUCCEEDED
;
954 else // if ( XSelected == aContinuations[1] )
956 // own lock on loading, user has selected to open readonly
957 // own lock on saving, user has selected to open readonly
958 // alien lock on loading, user has selected to retry saving
959 // TODO/LATER: alien lock on saving, user has selected to retry saving
962 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
964 nResult
= LOCK_UI_TRY
;
971 // if no interaction handler is provided the default answer is open readonly
972 // that usually happens in case the document is loaded per API
973 // so the document must be opened readonly for backward compatibility
974 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
977 SetError( ERRCODE_IO_ACCESSDENIED
, ::rtl::OUString( OSL_LOG_PREFIX
) );
986 bool isSuitableProtocolForLocking(const String
& rLogicName
)
988 INetURLObject
aUrl( rLogicName
);
989 INetProtocol eProt
= aUrl
.GetProtocol();
990 return eProt
== INET_PROT_FILE
|| eProt
== INET_PROT_SFTP
;
994 //------------------------------------------------------------------
995 sal_Bool
SfxMedium::LockOrigFileOnDemand( sal_Bool bLoading
, sal_Bool bNoUI
)
997 // returns true if the document can be opened for editing ( even if it should be a copy )
998 // otherwise the document should be opened readonly
999 // if user cancel the loading the ERROR_ABORT is set
1000 sal_Bool bResult
= sal_False
;
1002 if (!IsLockingUsed())
1007 if ( !GetURLObject().HasError() ) try
1009 if ( pImp
->m_bLocked
&& bLoading
&& ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
1011 // if the document is already locked the system locking might be temporarely off after storing
1012 // check whether the system file locking should be taken again
1013 GetLockingStream_Impl();
1016 bResult
= pImp
->m_bLocked
;
1020 // no read-write access is necessary on loading if the document is explicitly opened as copy
1021 SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem
, SfxBoolItem
, SID_TEMPLATE
, sal_False
);
1022 bResult
= ( bLoading
&& pTemplateItem
&& pTemplateItem
->GetValue() );
1025 if ( !bResult
&& !IsReadOnly() )
1027 sal_Bool bContentReadonly
= sal_False
;
1028 if ( bLoading
&& ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
1030 // let the original document be opened to check the possibility to open it for editing
1031 // and to let the writable stream stay open to hold the lock on the document
1032 GetLockingStream_Impl();
1035 // "IsReadOnly" property does not allow to detect whether the file is readonly always
1036 // so we try always to open the file for editing
1037 // the file is readonly only in case the read-write stream can not be opened
1038 if ( bLoading
&& !pImp
->m_xLockingStream
.is() )
1042 // MediaDescriptor does this check also, the duplication should be avoided in future
1043 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1044 ::ucbhelper::Content
aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
);
1045 aContent
.getPropertyValue( ::rtl::OUString( "IsReadOnly" ) ) >>= bContentReadonly
;
1047 catch( const uno::Exception
& )
1051 // This block was introduced as a fix to i#102464, but removing
1052 // this does not make the problem re-appear. But leaving this
1053 // part would interfere with documents saved in samba share. This
1054 // affects Windows only.
1055 if ( !bContentReadonly
)
1057 // the file is not readonly, check the ACL
1060 if ( ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), aPhysPath
) )
1061 bContentReadonly
= IsReadonlyAccordingACL( aPhysPath
.GetBuffer() );
1065 if ( bContentReadonly
)
1067 pImp
->m_originallyReadOnly
= true;
1071 // do further checks only if the file not readonly in fs
1072 if ( !bContentReadonly
)
1074 // the special file locking should be used only for suitable URLs
1075 if ( isSuitableProtocolForLocking( aLogicName
) )
1078 // in case of storing the document should request the output before locking
1081 // let the stream be opened to check the system file locking
1085 sal_Int8 bUIStatus
= LOCK_UI_NOLOCK
;
1087 // check whether system file locking has been used, the default value is false
1088 sal_Bool bUseSystemLock
= ::utl::LocalFileHelper::IsLocalFile( aLogicName
) && IsSystemFileLockingUsed();
1090 // TODO/LATER: This implementation does not allow to detect the system lock on saving here, actually this is no big problem
1091 // if system lock is used the writeable stream should be available
1092 sal_Bool bHandleSysLocked
= ( bLoading
&& bUseSystemLock
&& !pImp
->xStream
.is() && !pOutStream
);
1098 ::svt::DocumentLockFile
aLockFile( aLogicName
);
1099 if ( !bHandleSysLocked
)
1103 bResult
= aLockFile
.CreateOwnLockFile();
1105 catch ( const ucb::InteractiveIOException
& e
)
1107 // exception means that the lock file can not be successfuly accessed
1108 // in this case it should be ignored if system file locking is anyway active
1109 if ( bUseSystemLock
|| !IsOOoLockFileUsed() )
1112 // take the ownership over the lock file
1113 aLockFile
.OverwriteOwnLockFile();
1115 else if ( e
.Code
== IOErrorCode_INVALID_PARAMETER
)
1117 // system file locking is not active, ask user whether he wants to open the document without any locking
1118 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
1120 if ( xHandler
.is() )
1122 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xIgnoreRequestImpl
1123 = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
1125 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 2 );
1126 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl
.get() );
1127 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl
.get() );
1128 xIgnoreRequestImpl
->setContinuations( aContinuations
);
1130 xHandler
->handle( xIgnoreRequestImpl
.get() );
1132 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xIgnoreRequestImpl
->getSelection();
1133 bResult
= ( uno::Reference
< task::XInteractionApprove
>( xSelected
.get(), uno::UNO_QUERY
).is() );
1137 catch ( const uno::Exception
& )
1139 // exception means that the lock file can not be successfuly accessed
1140 // in this case it should be ignored if system file locking is anyway active
1141 if ( bUseSystemLock
|| !IsOOoLockFileUsed() )
1144 // take the ownership over the lock file
1145 aLockFile
.OverwriteOwnLockFile();
1149 // in case OOo locking is turned off the lock file is still written if possible
1150 // but it is ignored while deciding whether the document should be opened for editing or not
1151 if ( !bResult
&& !IsOOoLockFileUsed() )
1154 // take the ownership over the lock file
1155 aLockFile
.OverwriteOwnLockFile();
1162 uno::Sequence
< ::rtl::OUString
> aData
;
1165 // impossibility to get data is no real problem
1166 aData
= aLockFile
.GetLockData();
1168 catch( const uno::Exception
& )
1172 sal_Bool bOwnLock
= sal_False
;
1174 if ( !bHandleSysLocked
)
1176 uno::Sequence
< ::rtl::OUString
> aOwnData
= aLockFile
.GenerateOwnEntry();
1177 bOwnLock
= ( aData
.getLength() > LOCKFILE_USERURL_ID
1178 && aOwnData
.getLength() > LOCKFILE_USERURL_ID
1179 && aOwnData
[LOCKFILE_SYSUSERNAME_ID
].equals( aData
[LOCKFILE_SYSUSERNAME_ID
] ) );
1182 && aOwnData
[LOCKFILE_LOCALHOST_ID
].equals( aData
[LOCKFILE_LOCALHOST_ID
] )
1183 && aOwnData
[LOCKFILE_USERURL_ID
].equals( aData
[LOCKFILE_USERURL_ID
] ) )
1185 // this is own lock from the same installation, it could remain because of crash
1190 if ( !bResult
&& !bNoUI
)
1192 bUIStatus
= ShowLockedDocumentDialog( aData
, bLoading
, bOwnLock
);
1193 if ( bUIStatus
== LOCK_UI_SUCCEEDED
)
1195 // take the ownership over the lock file
1196 bResult
= aLockFile
.OverwriteOwnLockFile();
1200 bHandleSysLocked
= sal_False
;
1203 catch( const uno::Exception
& )
1206 } while( !bResult
&& bUIStatus
== LOCK_UI_TRY
);
1208 pImp
->m_bLocked
= bResult
;
1212 // this is no file URL, check whether the file is readonly
1213 bResult
= !bContentReadonly
;
1218 if ( !bResult
&& GetError() == ERRCODE_NONE
)
1220 // the error should be set in case it is storing process
1221 // or the document has been opened for editing explicitly
1223 SFX_ITEMSET_ARG( pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, sal_False
);
1224 if ( !bLoading
|| (pReadOnlyItem
&& !pReadOnlyItem
->GetValue()) )
1225 SetError( ERRCODE_IO_ACCESSDENIED
, ::rtl::OUString( OSL_LOG_PREFIX
) );
1227 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
1230 // when the file is locked, get the current file date
1231 if ( bResult
&& DocNeedsFileDateCheck() )
1232 GetInitFileDate( sal_True
);
1234 catch( const uno::Exception
& )
1236 OSL_FAIL( "Unexpected problem by locking, high probability, that the content could not be created" );
1241 //------------------------------------------------------------------
1242 uno::Reference
< embed::XStorage
> SfxMedium::GetStorage( sal_Bool bCreateTempIfNo
)
1244 if ( pImp
->xStorage
.is() || bTriedStorage
)
1245 return pImp
->xStorage
;
1247 uno::Sequence
< uno::Any
> aArgs( 2 );
1249 // the medium should be retrieved before temporary file creation
1250 // to let the MediaDescriptor be filled with the streams
1253 if ( bCreateTempIfNo
)
1254 CreateTempFile( sal_False
);
1259 return pImp
->xStorage
;
1261 SFX_ITEMSET_ARG( GetItemSet(), pRepairItem
, SfxBoolItem
, SID_REPAIRPACKAGE
, sal_False
);
1262 if ( pRepairItem
&& pRepairItem
->GetValue() )
1264 // the storage should be created for repairing mode
1265 CreateTempFile( sal_False
);
1268 Reference
< ::com::sun::star::ucb::XProgressHandler
> xProgressHandler
;
1269 Reference
< ::com::sun::star::task::XStatusIndicator
> xStatusIndicator
;
1271 SFX_ITEMSET_ARG( GetItemSet(), pxProgressItem
, SfxUnoAnyItem
, SID_PROGRESS_STATUSBAR_CONTROL
, sal_False
);
1272 if( pxProgressItem
&& ( pxProgressItem
->GetValue() >>= xStatusIndicator
) )
1273 xProgressHandler
= Reference
< ::com::sun::star::ucb::XProgressHandler
>(
1274 new utl::ProgressHandlerWrap( xStatusIndicator
) );
1276 uno::Sequence
< beans::PropertyValue
> aAddProps( 2 );
1277 aAddProps
[0].Name
= ::rtl::OUString("RepairPackage");
1278 aAddProps
[0].Value
<<= (sal_Bool
)sal_True
;
1279 aAddProps
[1].Name
= ::rtl::OUString("StatusIndicator");
1280 aAddProps
[1].Value
<<= xProgressHandler
;
1282 // the first arguments will be filled later
1284 aArgs
[2] <<= aAddProps
;
1287 if ( pImp
->xStream
.is() )
1289 // since the storage is based on temporary stream we open it always read-write
1290 aArgs
[0] <<= pImp
->xStream
;
1291 aArgs
[1] <<= embed::ElementModes::READWRITE
;
1292 pImp
->bStorageBasedOnInStream
= sal_True
;
1294 else if ( pImp
->xInputStream
.is() )
1296 // since the storage is based on temporary stream we open it always read-write
1297 aArgs
[0] <<= pImp
->xInputStream
;
1298 aArgs
[1] <<= embed::ElementModes::READ
;
1299 pImp
->bStorageBasedOnInStream
= sal_True
;
1303 CloseStreams_Impl();
1304 aArgs
[0] <<= ::rtl::OUString( aName
);
1305 aArgs
[1] <<= embed::ElementModes::READ
;
1306 pImp
->bStorageBasedOnInStream
= sal_False
;
1311 pImp
->xStorage
= uno::Reference
< embed::XStorage
>(
1312 ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs
),
1315 catch( const uno::Exception
& )
1317 // impossibility to create the storage is no error
1320 if( ( pImp
->nLastStorageError
= GetError() ) != SVSTREAM_OK
)
1325 return uno::Reference
< embed::XStorage
>();
1328 bTriedStorage
= sal_True
;
1330 // TODO/LATER: Get versionlist on demand
1331 if ( pImp
->xStorage
.is() )
1333 SetEncryptionDataToStorage_Impl();
1337 SFX_ITEMSET_ARG( pSet
, pVersion
, SfxInt16Item
, SID_VERSION
, sal_False
);
1339 sal_Bool bResetStorage
= sal_False
;
1340 if ( pVersion
&& pVersion
->GetValue() )
1342 // Read all available versions
1343 if ( pImp
->aVersions
.getLength() )
1345 // Search for the version fits the comment
1346 // The versions are numbered startign with 1, versions with
1347 // negative versions numbers are counted backwards from the
1349 short nVersion
= pVersion
? pVersion
->GetValue() : 0;
1351 nVersion
= ( (short) pImp
->aVersions
.getLength() ) + nVersion
;
1352 else if ( nVersion
)
1355 util::RevisionTag
& rTag
= pImp
->aVersions
[nVersion
];
1357 // Open SubStorage for all versions
1358 uno::Reference
< embed::XStorage
> xSub
= pImp
->xStorage
->openStorageElement( DEFINE_CONST_UNICODE( "Versions" ),
1359 embed::ElementModes::READ
);
1361 DBG_ASSERT( xSub
.is(), "Version list, but no Versions!" );
1363 // There the version is stored as packed Stream
1364 uno::Reference
< io::XStream
> xStr
= xSub
->openStreamElement( rTag
.Identifier
, embed::ElementModes::READ
);
1365 SvStream
* pStream
= utl::UcbStreamHelper::CreateStream( xStr
);
1366 if ( pStream
&& pStream
->GetError() == SVSTREAM_OK
)
1368 // Unpack Stream in TempDir
1369 ::utl::TempFile aTempFile
;
1370 String aTmpName
= aTempFile
.GetURL();
1371 SvFileStream
aTmpStream( aTmpName
, SFX_STREAM_READWRITE
);
1373 *pStream
>> aTmpStream
;
1376 // Open data as Storage
1377 nStorOpenMode
= SFX_STREAM_READONLY
;
1378 pImp
->xStorage
= comphelper::OStorageHelper::GetStorageFromURL( aTmpName
, embed::ElementModes::READ
);
1379 pImp
->bStorageBasedOnInStream
= sal_False
;
1380 rtl::OUString aTemp
;
1381 ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName
, aTemp
);
1382 SetPhysicalName_Impl( aTemp
);
1384 pImp
->bIsTemp
= sal_True
;
1385 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
1387 pImp
->aVersions
.realloc(0);
1390 bResetStorage
= sal_True
;
1394 bResetStorage
= sal_True
;
1397 if ( bResetStorage
)
1401 pInStream
->Seek( 0L );
1404 pImp
->bIsStorage
= pImp
->xStorage
.is();
1405 return pImp
->xStorage
;
1408 //------------------------------------------------------------------
1409 uno::Reference
< embed::XStorage
> SfxMedium::GetZipStorageToSign_Impl( sal_Bool bReadOnly
)
1411 if ( !GetError() && !pImp
->m_xZipStorage
.is() )
1417 // we can not sign document if there is no stream
1418 // should it be possible at all?
1419 if ( !bReadOnly
&& pImp
->xStream
.is() )
1421 pImp
->m_xZipStorage
= ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xStream
, embed::ElementModes::READWRITE
);
1423 else if ( pImp
->xInputStream
.is() )
1425 pImp
->m_xZipStorage
= ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xInputStream
);
1428 catch( const uno::Exception
& )
1430 OSL_FAIL( "No possibility to get readonly version of storage from medium!\n" );
1433 if ( GetError() ) // do not remove warnings
1437 return pImp
->m_xZipStorage
;
1440 //------------------------------------------------------------------
1441 void SfxMedium::CloseZipStorage_Impl()
1443 if ( pImp
->m_xZipStorage
.is() )
1446 pImp
->m_xZipStorage
->dispose();
1447 } catch( const uno::Exception
& )
1450 pImp
->m_xZipStorage
= uno::Reference
< embed::XStorage
>();
1454 //------------------------------------------------------------------
1455 void SfxMedium::CloseStorage()
1457 if ( pImp
->xStorage
.is() )
1459 uno::Reference
< lang::XComponent
> xComp( pImp
->xStorage
, uno::UNO_QUERY
);
1460 // in the salvage mode the medium does not own the storage
1461 if ( pImp
->bDisposeStorage
&& !pImp
->m_bSalvageMode
)
1465 } catch( const uno::Exception
& )
1467 OSL_FAIL( "Medium's storage is already disposed!\n" );
1472 pImp
->bStorageBasedOnInStream
= sal_False
;
1475 bTriedStorage
= sal_False
;
1476 pImp
->bIsStorage
= sal_False
;
1479 void SfxMedium::CanDisposeStorage_Impl( sal_Bool bDisposeStorage
)
1481 pImp
->bDisposeStorage
= bDisposeStorage
;
1484 sal_Bool
SfxMedium::WillDisposeStorageOnClose_Impl()
1486 return pImp
->bDisposeStorage
;
1489 //------------------------------------------------------------------
1490 void SfxMedium::SetOpenMode( StreamMode nStorOpen
,
1491 sal_Bool bDontClose
)
1493 if ( nStorOpenMode
!= nStorOpen
)
1495 nStorOpenMode
= nStorOpen
;
1499 if ( pImp
->xStorage
.is() )
1502 CloseStreams_Impl();
1506 bSetFilter
= sal_False
;
1509 //------------------------------------------------------------------
1510 sal_Bool
SfxMedium::UseBackupToRestore_Impl( ::ucbhelper::Content
& aOriginalContent
,
1511 const Reference
< ::com::sun::star::ucb::XCommandEnvironment
>& xComEnv
)
1515 ::ucbhelper::Content
aTransactCont( pImp
->m_aBackupURL
, xComEnv
);
1517 Reference
< XInputStream
> aOrigInput
= aTransactCont
.openStream();
1518 aOriginalContent
.writeStream( aOrigInput
, sal_True
);
1521 catch( const Exception
& )
1523 // in case of failure here the backup file should not be removed
1524 // TODO/LATER: a message should be used to let user know about the backup
1525 pImp
->m_bRemoveBackup
= sal_False
;
1526 // TODO/LATER: needs a specific error code
1527 eError
= ERRCODE_IO_GENERAL
;
1533 //------------------------------------------------------------------
1534 sal_Bool
SfxMedium::StorageCommit_Impl()
1536 sal_Bool bResult
= sal_False
;
1537 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1538 ::ucbhelper::Content aOriginalContent
;
1540 if ( pImp
->xStorage
.is() )
1544 uno::Reference
< embed::XTransactedObject
> xTrans( pImp
->xStorage
, uno::UNO_QUERY
);
1550 CloseZipStorage_Impl();
1553 catch ( const embed::UseBackupException
& aBackupExc
)
1555 // since the temporary file is created always now, the scenario is close to be impossible
1556 if ( !pImp
->pTempFile
)
1558 OSL_ENSURE( !pImp
->m_aBackupURL
.isEmpty(), "No backup on storage commit!\n" );
1559 if ( !pImp
->m_aBackupURL
.isEmpty()
1560 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
),
1562 aOriginalContent
) )
1564 // use backup to restore the file
1565 // the storage has already disconnected from original location
1566 CloseAndReleaseStreams_Impl();
1567 if ( !UseBackupToRestore_Impl( aOriginalContent
, xDummyEnv
) )
1569 // connect the medium to the temporary file of the storage
1570 pImp
->aContent
= ::ucbhelper::Content();
1571 aName
= aBackupExc
.TemporaryFileURL
;
1572 OSL_ENSURE( !aName
.isEmpty(), "The exception _must_ contain the temporary URL!\n" );
1577 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( OSL_LOG_PREFIX
) );
1580 catch ( const uno::Exception
& )
1582 //TODO/LATER: improve error handling
1583 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( OSL_LOG_PREFIX
) );
1592 //------------------------------------------------------------------
1593 sal_Bool
SfxMedium::TransactedTransferForFS_Impl( const INetURLObject
& aSource
,
1594 const INetURLObject
& aDest
,
1595 const Reference
< ::com::sun::star::ucb::XCommandEnvironment
>& xComEnv
)
1597 sal_Bool bResult
= sal_False
;
1598 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1599 Reference
< XOutputStream
> aDestStream
;
1600 ::ucbhelper::Content aOriginalContent
;
1604 aOriginalContent
= ::ucbhelper::Content( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
1606 catch ( const ::com::sun::star::ucb::CommandAbortedException
& )
1608 eError
= ERRCODE_ABORT
;
1610 catch ( const ::com::sun::star::ucb::CommandFailedException
& )
1612 eError
= ERRCODE_ABORT
;
1614 catch (const ::com::sun::star::ucb::ContentCreationException
& ex
)
1616 eError
= ERRCODE_IO_GENERAL
;
1618 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER
) ||
1619 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED
)
1622 eError
= ERRCODE_IO_NOTEXISTSPATH
;
1625 catch (const ::com::sun::star::uno::Exception
&)
1627 eError
= ERRCODE_IO_GENERAL
;
1630 if( !eError
|| (eError
& ERRCODE_WARNING_MASK
) )
1632 if ( pImp
->xStorage
.is() )
1635 CloseStreams_Impl();
1637 ::ucbhelper::Content aTempCont
;
1638 if( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, aTempCont
) )
1640 sal_Bool bTransactStarted
= sal_False
;
1641 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, sal_False
);
1642 SFX_ITEMSET_ARG( GetItemSet(), pRename
, SfxBoolItem
, SID_RENAME
, sal_False
);
1643 sal_Bool bRename
= pRename
? pRename
->GetValue() : sal_False
;
1644 sal_Bool bOverWrite
= pOverWrite
? pOverWrite
->GetValue() : !bRename
;
1648 if( bOverWrite
&& ::utl::UCBContentHelper::IsDocument( aDest
.GetMainURL( INetURLObject::NO_DECODE
) ) )
1650 if( pImp
->m_aBackupURL
.isEmpty() )
1651 DoInternalBackup_Impl( aOriginalContent
);
1653 if( !pImp
->m_aBackupURL
.isEmpty() )
1655 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1656 bTransactStarted
= sal_True
;
1657 aOriginalContent
.setPropertyValue( ::rtl::OUString("Size"),
1658 uno::makeAny( (sal_Int64
)0 ) );
1659 aOriginalContent
.writeStream( aTempInput
, bOverWrite
);
1664 eError
= ERRCODE_SFX_CANTCREATEBACKUP
;
1669 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1670 aOriginalContent
.writeStream( aTempInput
, bOverWrite
);
1674 catch ( const ::com::sun::star::ucb::CommandAbortedException
& )
1676 eError
= ERRCODE_ABORT
;
1678 catch ( const ::com::sun::star::ucb::CommandFailedException
& )
1680 eError
= ERRCODE_ABORT
;
1682 catch ( const ::com::sun::star::ucb::InteractiveIOException
& r
)
1684 if ( r
.Code
== IOErrorCode_ACCESS_DENIED
)
1685 eError
= ERRCODE_IO_ACCESSDENIED
;
1686 else if ( r
.Code
== IOErrorCode_NOT_EXISTING
)
1687 eError
= ERRCODE_IO_NOTEXISTS
;
1688 else if ( r
.Code
== IOErrorCode_CANT_READ
)
1689 eError
= ERRCODE_IO_CANTREAD
;
1691 eError
= ERRCODE_IO_GENERAL
;
1693 catch ( const ::com::sun::star::uno::Exception
& )
1695 eError
= ERRCODE_IO_GENERAL
;
1700 if ( pImp
->pTempFile
)
1702 pImp
->pTempFile
->EnableKillingFile( sal_True
);
1703 delete pImp
->pTempFile
;
1704 pImp
->pTempFile
= NULL
;
1707 else if ( bTransactStarted
)
1709 UseBackupToRestore_Impl( aOriginalContent
, xDummyEnv
);
1713 eError
= ERRCODE_IO_CANTREAD
;
1719 //------------------------------------------------------------------
1720 sal_Bool
SfxMedium::TryDirectTransfer( const ::rtl::OUString
& aURL
, SfxItemSet
& aTargetSet
)
1725 // if the document had no password it should be stored without password
1726 // if the document had password it should be stored with the same password
1727 // otherwise the stream copying can not be done
1728 SFX_ITEMSET_ARG( &aTargetSet
, pNewPassItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
1729 SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
1730 if ( ( !pNewPassItem
&& !pOldPassItem
)
1731 || ( pNewPassItem
&& pOldPassItem
&& pNewPassItem
->GetValue().Equals( pOldPassItem
->GetValue() ) ) )
1733 // the filter must be the same
1734 SFX_ITEMSET_ARG( &aTargetSet
, pNewFilterItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
1735 SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
1736 if ( pNewFilterItem
&& pOldFilterItem
&& pNewFilterItem
->GetValue().Equals( pOldFilterItem
->GetValue() ) )
1738 // get the input stream and copy it
1739 // in case of success return true
1740 uno::Reference
< io::XInputStream
> xInStream
= GetInputStream();
1743 if ( xInStream
.is() )
1747 uno::Reference
< io::XSeekable
> xSeek( xInStream
, uno::UNO_QUERY
);
1751 nPos
= xSeek
->getPosition();
1755 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
1756 ::ucbhelper::Content
aTargetContent( aURL
, xEnv
);
1758 InsertCommandArgument aInsertArg
;
1759 aInsertArg
.Data
= xInStream
;
1760 SFX_ITEMSET_ARG( &aTargetSet
, pRename
, SfxBoolItem
, SID_RENAME
, sal_False
);
1761 SFX_ITEMSET_ARG( &aTargetSet
, pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, sal_False
);
1762 if ( (pOverWrite
&& !pOverWrite
->GetValue()) // argument says: never overwrite
1763 || (pRename
&& pRename
->GetValue()) ) // argument says: rename file
1764 aInsertArg
.ReplaceExisting
= sal_False
;
1766 aInsertArg
.ReplaceExisting
= sal_True
; // default is overwrite existing files
1769 aCmdArg
<<= aInsertArg
;
1770 aTargetContent
.executeCommand( ::rtl::OUString( "insert" ),
1774 xSeek
->seek( nPos
);
1778 catch( const uno::Exception
& )
1787 //------------------------------------------------------------------
1788 void SfxMedium::Transfer_Impl()
1790 // The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
1791 rtl::OUString aNameURL
;
1792 if ( pImp
->pTempFile
)
1793 aNameURL
= pImp
->pTempFile
->GetURL();
1794 else if ( aLogicName
.Len() && pImp
->m_bSalvageMode
)
1796 // makes sence only in case logic name is set
1797 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aNameURL
) )
1798 OSL_FAIL( "The medium name is not convertable!\n" );
1801 if ( !aNameURL
.isEmpty() && ( !eError
|| (eError
& ERRCODE_WARNING_MASK
) ) )
1803 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::Transfer_Impl, copying to target" );
1805 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
1806 Reference
< XOutputStream
> rOutStream
;
1808 // in case an output stream is provided from outside and the URL is correct
1809 // commit to the stream
1810 if( aLogicName
.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL
)
1812 // TODO/LATER: support storing to SID_STREAM
1813 SFX_ITEMSET_ARG( pSet
, pOutStreamItem
, SfxUnoAnyItem
, SID_OUTPUTSTREAM
, sal_False
);
1814 if( pOutStreamItem
&& ( pOutStreamItem
->GetValue() >>= rOutStream
) )
1816 if ( pImp
->xStorage
.is() )
1819 CloseStreams_Impl();
1821 INetURLObject
aSource( aNameURL
);
1822 ::ucbhelper::Content aTempCont
;
1823 if( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, aTempCont
) )
1828 sal_Int32 nBufferSize
= 32767;
1829 Sequence
< sal_Int8
> aSequence ( nBufferSize
);
1830 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1834 nRead
= aTempInput
->readBytes ( aSequence
, nBufferSize
);
1835 if ( nRead
< nBufferSize
)
1837 Sequence
< sal_Int8
> aTempBuf ( aSequence
.getConstArray(), nRead
);
1838 rOutStream
->writeBytes ( aTempBuf
);
1841 rOutStream
->writeBytes ( aSequence
);
1843 while ( nRead
== nBufferSize
);
1845 // remove temporary file
1846 if ( pImp
->pTempFile
)
1848 pImp
->pTempFile
->EnableKillingFile( sal_True
);
1849 delete pImp
->pTempFile
;
1850 pImp
->pTempFile
= NULL
;
1853 catch( const Exception
& )
1859 OSL_FAIL( "Illegal Output stream parameter!\n" );
1860 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( OSL_LOG_PREFIX
) );
1863 // free the reference
1865 pSet
->ClearItem( SID_OUTPUTSTREAM
);
1871 if ( !pImp
->aContent
.get().is() )
1873 eError
= ERRCODE_IO_NOTEXISTS
;
1877 SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize
, SfxInt32Item
, SID_SEGMENTSIZE
, sal_False
);
1880 // this file must be stored into a disk spanned package
1883 uno::Reference
< embed::XStorage
> xStor
= comphelper::OStorageHelper::GetStorageFromURL( GetName(),
1884 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1886 // set segment size property; package will automatically be divided in pieces fitting
1888 ::com::sun::star::uno::Any aAny
;
1889 aAny
<<= pSegmentSize
->GetValue();
1891 uno::Reference
< beans::XPropertySet
> xSet( pImp
->xStorage
, uno::UNO_QUERY
);
1892 xSet
->setPropertyValue( String::CreateFromAscii("SegmentSize"), aAny
);
1894 // copy the temporary storage into the disk spanned package
1895 GetStorage()->copyToStorage( xStor
);
1896 uno::Reference
< embed::XTransactedObject
> xTrans( pImp
->xStorage
, uno::UNO_QUERY
);
1901 catch ( const uno::Exception
& )
1903 //TODO/MBA: error handling
1908 INetURLObject
aDest( GetURLObject() );
1910 // source is the temp file written so far
1911 INetURLObject
aSource( aNameURL
);
1913 // a special case, an interaction handler should be used for
1914 // authentication in case it is available
1915 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
1916 Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler
= GetInteractionHandler();
1917 if (xInteractionHandler
.is())
1918 xComEnv
= new ::ucbhelper::CommandEnvironment( xInteractionHandler
,
1919 Reference
< ::com::sun::star::ucb::XProgressHandler
>() );
1921 rtl::OUString
aDestURL( aDest
.GetMainURL( INetURLObject::NO_DECODE
) );
1923 if ( ::utl::LocalFileHelper::IsLocalFile( aDestURL
) || !aDest
.removeSegment() )
1925 TransactedTransferForFS_Impl( aSource
, aDest
, xComEnv
);
1927 // Hideous - no clean way to do this, so we re-open the file just to fsync it
1928 osl::File
aFile( aDestURL
);
1929 if ( aFile
.open( osl_File_OpenFlag_Write
) == osl::FileBase::E_None
)
1932 OSL_TRACE("fsync'd saved file '%s'\n",
1933 rtl::OUStringToOString( aDestURL
, RTL_TEXTENCODING_UTF8
).getStr() );
1939 // create content for the parent folder and call transfer on that content with the source content
1940 // and the destination file name as parameters
1941 ::ucbhelper::Content aSourceContent
;
1942 ::ucbhelper::Content aTransferContent
;
1944 // Get the parent URL from the XChild if possible: why would the URL necessarily have
1945 // a hierarchical path? It's not the case for CMIS.
1946 ::ucbhelper::Content aDestContent
;
1947 ::ucbhelper::Content::create( aDestURL
, xComEnv
, aDestContent
);
1948 Reference
< ::com::sun::star::container::XChild
> xChild( aDestContent
.get(), uno::UNO_QUERY
);
1949 rtl::OUString sParentUrl
;
1952 Reference
< ::com::sun::star::ucb::XContent
> xParent( xChild
->getParent( ), uno::UNO_QUERY
);
1953 if ( xParent
.is( ) )
1955 sParentUrl
= xParent
->getIdentifier( )->getContentIdentifier();
1959 if ( !sParentUrl
.isEmpty() )
1960 aDest
= INetURLObject( sParentUrl
);
1962 // LongName wasn't defined anywhere, only used here... get the Title instead
1963 // as it's less probably empty
1964 rtl::OUString aFileName
;
1965 Any aAny
= aDestContent
.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Title" )) );
1967 if ( aFileName
.isEmpty() )
1968 aFileName
= GetURLObject().getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
1972 aTransferContent
= ::ucbhelper::Content( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
1974 catch (const ::com::sun::star::ucb::ContentCreationException
& ex
)
1976 eError
= ERRCODE_IO_GENERAL
;
1978 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER
) ||
1979 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED
)
1982 eError
= ERRCODE_IO_NOTEXISTSPATH
;
1985 catch (const ::com::sun::star::uno::Exception
&)
1987 eError
= ERRCODE_IO_GENERAL
;
1990 if ( !eError
|| (eError
& ERRCODE_WARNING_MASK
) )
1992 // free resources, otherwise the transfer may fail
1993 if ( pImp
->xStorage
.is() )
1996 CloseStreams_Impl();
1998 ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, aSourceContent
);
2000 // check for external parameters that may customize the handling of NameClash situations
2001 SFX_ITEMSET_ARG( GetItemSet(), pRename
, SfxBoolItem
, SID_RENAME
, sal_False
);
2002 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, sal_False
);
2003 sal_Int32 nNameClash
;
2004 if ( pOverWrite
&& !pOverWrite
->GetValue() )
2005 // argument says: never overwrite
2006 nNameClash
= NameClash::ERROR
;
2007 else if ( pRename
&& pRename
->GetValue() )
2008 // argument says: rename file
2009 nNameClash
= NameClash::RENAME
;
2011 // default is overwrite existing files
2012 nNameClash
= NameClash::OVERWRITE
;
2016 if (!aTransferContent
.transferContent( aSourceContent
, ::ucbhelper::InsertOperation_COPY
, aFileName
, nNameClash
))
2017 eError
= ERRCODE_IO_GENERAL
;
2019 catch ( const ::com::sun::star::ucb::CommandAbortedException
& )
2021 eError
= ERRCODE_ABORT
;
2023 catch ( const ::com::sun::star::ucb::CommandFailedException
& )
2025 eError
= ERRCODE_ABORT
;
2027 catch ( const ::com::sun::star::ucb::InteractiveIOException
& r
)
2029 if ( r
.Code
== IOErrorCode_ACCESS_DENIED
)
2030 eError
= ERRCODE_IO_ACCESSDENIED
;
2031 else if ( r
.Code
== IOErrorCode_NOT_EXISTING
)
2032 eError
= ERRCODE_IO_NOTEXISTS
;
2033 else if ( r
.Code
== IOErrorCode_CANT_READ
)
2034 eError
= ERRCODE_IO_CANTREAD
;
2036 eError
= ERRCODE_IO_GENERAL
;
2038 catch ( const ::com::sun::star::uno::Exception
& )
2040 eError
= ERRCODE_IO_GENERAL
;
2043 // do not switch from temporary file in case of nonfile protocol
2047 if ( ( !eError
|| (eError
& ERRCODE_WARNING_MASK
) ) && !pImp
->pTempFile
)
2049 // without a TempFile the physical and logical name should be the same after successful transfer
2050 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
),
2052 pImp
->m_bSalvageMode
= sal_False
;
2057 //------------------------------------------------------------------
2058 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content
& aOriginalContent
,
2059 const String
& aPrefix
,
2060 const String
& aExtension
,
2061 const String
& aDestDir
)
2063 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::DoInternalBackup_Impl( with destdir )" );
2065 if ( !pImp
->m_aBackupURL
.isEmpty() )
2066 return; // the backup was done already
2068 ::utl::TempFile
aTransactTemp( aPrefix
, &aExtension
, &aDestDir
);
2069 aTransactTemp
.EnableKillingFile( sal_False
);
2071 INetURLObject
aBackObj( aTransactTemp
.GetURL() );
2072 ::rtl::OUString aBackupName
= aBackObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2074 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
2075 ::ucbhelper::Content aBackupCont
;
2076 if( ::ucbhelper::Content::create( aDestDir
, xDummyEnv
, aBackupCont
) )
2080 if( aBackupCont
.transferContent( aOriginalContent
,
2081 ::ucbhelper::InsertOperation_COPY
,
2083 NameClash::OVERWRITE
) )
2085 pImp
->m_aBackupURL
= aBackObj
.GetMainURL( INetURLObject::NO_DECODE
);
2086 pImp
->m_bRemoveBackup
= sal_True
;
2089 catch( const Exception
& )
2093 if ( pImp
->m_aBackupURL
.isEmpty() )
2094 aTransactTemp
.EnableKillingFile( sal_True
);
2097 //------------------------------------------------------------------
2098 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content
& aOriginalContent
)
2100 if ( !pImp
->m_aBackupURL
.isEmpty() )
2101 return; // the backup was done already
2103 ::rtl::OUString aFileName
= GetURLObject().getName( INetURLObject::LAST_SEGMENT
,
2105 INetURLObject::NO_DECODE
);
2107 sal_Int32 nPrefixLen
= aFileName
.lastIndexOf( '.' );
2108 String aPrefix
= ( nPrefixLen
== -1 ) ? aFileName
: aFileName
.copy( 0, nPrefixLen
);
2109 String aExtension
= ( nPrefixLen
== -1 ) ? String() : String(aFileName
.copy( nPrefixLen
));
2110 String aBakDir
= SvtPathOptions().GetBackupPath();
2112 DoInternalBackup_Impl( aOriginalContent
, aPrefix
, aExtension
, aBakDir
);
2114 if ( pImp
->m_aBackupURL
.isEmpty() )
2116 // the copiing to the backup catalog failed ( for example because
2117 // of using an encrypted partition as target catalog )
2118 // since the user did not specify to make backup explicitly
2119 // office should try to make backup in another place,
2120 // target catalog does not look bad for this case ( and looks
2121 // to be the only way for encrypted partitions )
2123 INetURLObject aDest
= GetURLObject();
2124 if ( aDest
.removeSegment() )
2125 DoInternalBackup_Impl( aOriginalContent
, aPrefix
, aExtension
, aDest
.GetMainURL( INetURLObject::NO_DECODE
) );
2130 //------------------------------------------------------------------
2131 void SfxMedium::DoBackup_Impl()
2133 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::DoBackup_Impl" );
2135 // source file name is the logical name of this medium
2136 INetURLObject
aSource( GetURLObject() );
2138 // there is nothing to backup in case source file does not exist
2139 if ( !::utl::UCBContentHelper::IsDocument( aSource
.GetMainURL( INetURLObject::NO_DECODE
) ) )
2142 sal_Bool bSuccess
= sal_False
;
2144 // get path for backups
2145 String aBakDir
= SvtPathOptions().GetBackupPath();
2148 // create content for the parent folder ( = backup folder )
2149 ::ucbhelper::Content aContent
;
2150 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
2151 if( ::ucbhelper::Content::create( aBakDir
, xEnv
, aContent
) )
2153 // save as ".bak" file
2154 INetURLObject
aDest( aBakDir
);
2155 aDest
.insertName( aSource
.getName() );
2156 aDest
.setExtension( DEFINE_CONST_UNICODE( "bak" ) );
2157 String aFileName
= aDest
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2159 // create a content for the source file
2160 ::ucbhelper::Content aSourceContent
;
2161 if ( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, aSourceContent
) )
2165 // do the transfer ( copy source file to backup dir )
2166 bSuccess
= aContent
.transferContent( aSourceContent
,
2167 ::ucbhelper::InsertOperation_COPY
,
2169 NameClash::OVERWRITE
);
2172 pImp
->m_aBackupURL
= aDest
.GetMainURL( INetURLObject::NO_DECODE
);
2173 pImp
->m_bRemoveBackup
= sal_False
;
2176 catch ( const ::com::sun::star::uno::Exception
& )
2185 eError
= ERRCODE_SFX_CANTCREATEBACKUP
;
2189 //------------------------------------------------------------------
2190 void SfxMedium::ClearBackup_Impl()
2192 if( pImp
->m_bRemoveBackup
)
2194 // currently a document is always stored in a new medium,
2195 // thus if a backup can not be removed the backup URL should not be cleaned
2196 if ( !pImp
->m_aBackupURL
.isEmpty() )
2198 if ( ::utl::UCBContentHelper::Kill( pImp
->m_aBackupURL
) )
2200 pImp
->m_bRemoveBackup
= sal_False
;
2201 pImp
->m_aBackupURL
= ::rtl::OUString();
2206 OSL_FAIL("Couldn't remove backup file!");
2211 pImp
->m_aBackupURL
= ::rtl::OUString();
2214 //----------------------------------------------------------------
2215 void SfxMedium::GetLockingStream_Impl()
2217 if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
2218 && !pImp
->m_xLockingStream
.is() )
2220 SFX_ITEMSET_ARG( pSet
, pWriteStreamItem
, SfxUnoAnyItem
, SID_STREAM
, sal_False
);
2221 if ( pWriteStreamItem
)
2222 pWriteStreamItem
->GetValue() >>= pImp
->m_xLockingStream
;
2224 if ( !pImp
->m_xLockingStream
.is() )
2226 // open the original document
2227 uno::Sequence
< beans::PropertyValue
> xProps
;
2228 TransformItems( SID_OPENDOC
, *GetItemSet(), xProps
);
2229 comphelper::MediaDescriptor
aMedium( xProps
);
2231 aMedium
.addInputStreamOwnLock();
2233 uno::Reference
< io::XInputStream
> xInputStream
;
2234 aMedium
[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp
->m_xLockingStream
;
2235 aMedium
[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream
;
2237 if ( !pImp
->pTempFile
&& aName
.isEmpty() )
2239 // the medium is still based on the original file, it makes sence to initialize the streams
2240 if ( pImp
->m_xLockingStream
.is() )
2241 pImp
->xStream
= pImp
->m_xLockingStream
;
2243 if ( xInputStream
.is() )
2244 pImp
->xInputStream
= xInputStream
;
2246 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2247 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2253 //----------------------------------------------------------------
2254 void SfxMedium::GetMedium_Impl()
2258 pImp
->bDownloadDone
= sal_False
;
2259 Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler
= GetInteractionHandler();
2261 //TODO/MBA: need support for SID_STREAM
2262 SFX_ITEMSET_ARG( pSet
, pWriteStreamItem
, SfxUnoAnyItem
, SID_STREAM
, sal_False
);
2263 SFX_ITEMSET_ARG( pSet
, pInStreamItem
, SfxUnoAnyItem
, SID_INPUTSTREAM
, sal_False
);
2264 if ( pWriteStreamItem
)
2266 pWriteStreamItem
->GetValue() >>= pImp
->xStream
;
2268 if ( pInStreamItem
)
2269 pInStreamItem
->GetValue() >>= pImp
->xInputStream
;
2271 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2272 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2274 else if ( pInStreamItem
)
2276 pInStreamItem
->GetValue() >>= pImp
->xInputStream
;
2280 uno::Sequence
< beans::PropertyValue
> xProps
;
2281 rtl::OUString aFileName
;
2282 if (!aName
.isEmpty())
2284 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aFileName
) )
2286 OSL_FAIL("Physical name not convertable!");
2290 aFileName
= GetName();
2292 // in case the temporary file exists the streams should be initialized from it,
2293 // but the original MediaDescriptor should not be changed
2294 sal_Bool bFromTempFile
= ( pImp
->pTempFile
!= NULL
);
2296 if ( !bFromTempFile
)
2298 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, aFileName
) );
2299 if( !(nStorOpenMode
& STREAM_WRITE
) )
2300 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
2301 if (xInteractionHandler
.is())
2302 GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER
, makeAny(xInteractionHandler
) ) );
2305 if ( m_xInputStreamToLoadFrom
.is() )
2307 pImp
->xInputStream
= m_xInputStreamToLoadFrom
;
2308 pImp
->xInputStream
->skipBytes(0);
2309 if(m_bInputStreamIsReadOnly
)
2310 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
2314 TransformItems( SID_OPENDOC
, *GetItemSet(), xProps
);
2315 comphelper::MediaDescriptor
aMedium( xProps
);
2317 if ( pImp
->m_xLockingStream
.is() && !bFromTempFile
)
2319 // the medium is not based on the temporary file, so the original stream can be used
2320 pImp
->xStream
= pImp
->m_xLockingStream
;
2324 if ( bFromTempFile
)
2326 aMedium
[comphelper::MediaDescriptor::PROP_URL()] <<= ::rtl::OUString( aFileName
);
2327 aMedium
.erase( comphelper::MediaDescriptor::PROP_READONLY() );
2328 aMedium
.addInputStream();
2330 else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
2332 // use the special locking approach only for file URLs
2333 aMedium
.addInputStreamOwnLock();
2336 aMedium
.addInputStream();
2338 // the ReadOnly property set in aMedium is ignored
2339 // the check is done in LockOrigFileOnDemand() for file and non-file URLs
2341 //TODO/MBA: what happens if property is not there?!
2342 aMedium
[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp
->xStream
;
2343 aMedium
[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp
->xInputStream
;
2347 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2348 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2351 if ( !bFromTempFile
)
2353 //TODO/MBA: need support for SID_STREAM
2354 if ( pImp
->xStream
.is() )
2355 GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM
, makeAny( pImp
->xStream
) ) );
2357 GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM
, makeAny( pImp
->xInputStream
) ) );
2361 //TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
2362 if ( !GetError() && !pImp
->xStream
.is() && !pImp
->xInputStream
.is() )
2363 SetError( ERRCODE_IO_ACCESSDENIED
, ::rtl::OUString( OSL_LOG_PREFIX
) );
2367 if ( pImp
->xStream
.is() )
2368 pInStream
= utl::UcbStreamHelper::CreateStream( pImp
->xStream
);
2369 else if ( pImp
->xInputStream
.is() )
2370 pInStream
= utl::UcbStreamHelper::CreateStream( pImp
->xInputStream
);
2373 pImp
->bDownloadDone
= sal_True
;
2374 pImp
->aDoneLink
.ClearPendingCall();
2375 sal_uIntPtr nError
= GetError();
2376 pImp
->aDoneLink
.Call( (void*)nError
);
2380 //----------------------------------------------------------------
2381 sal_Bool
SfxMedium::IsRemote()
2386 //------------------------------------------------------------------
2388 void SfxMedium::SetUpdatePickList(sal_Bool bVal
)
2391 pImp
= new SfxMedium_Impl( this );
2392 pImp
->bUpdatePickList
= bVal
;
2394 //------------------------------------------------------------------
2396 sal_Bool
SfxMedium::IsUpdatePickList() const
2398 return pImp
? pImp
->bUpdatePickList
: sal_True
;
2400 //----------------------------------------------------------------
2402 void SfxMedium::SetDoneLink( const Link
& rLink
)
2404 pImp
->aDoneLink
= rLink
;
2407 //----------------------------------------------------------------
2409 void SfxMedium::SetDataAvailableLink( const Link
& rLink
)
2411 pImp
->aAvailableLink
= rLink
;
2414 void SfxMedium::DownLoad( const Link
& aLink
)
2416 SetDoneLink( aLink
);
2418 if ( pInStream
&& !aLink
.IsSet() )
2420 while( !pImp
->bDownloadDone
)
2421 Application::Yield();
2425 //------------------------------------------------------------------
2426 void SfxMedium::Init_Impl()
2428 Includes a valid:: sun:: com:: star:: util:: URL (If a file name was
2429 previously in there) in the logical name and if available sets the
2430 physical name as the file name.
2434 Reference
< XOutputStream
> rOutStream
;
2436 // TODO/LATER: handle lifetime of storages
2437 pImp
->bDisposeStorage
= sal_False
;
2439 SFX_ITEMSET_ARG( pSet
, pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, sal_False
);
2440 if ( pSalvageItem
&& !pSalvageItem
->GetValue().Len() )
2442 pSalvageItem
= NULL
;
2443 pSet
->ClearItem( SID_DOC_SALVAGE
);
2446 if( aLogicName
.Len() )
2448 INetURLObject
aUrl( aLogicName
);
2449 INetProtocol eProt
= aUrl
.GetProtocol();
2450 if ( eProt
== INET_PROT_NOT_VALID
)
2452 OSL_FAIL( "Unknown protocol!" );
2456 if ( aUrl
.HasMark() )
2458 aLogicName
= aUrl
.GetURLNoMark( INetURLObject::NO_DECODE
);
2459 GetItemSet()->Put( SfxStringItem( SID_JUMPMARK
, aUrl
.GetMark() ) );
2462 // try to convert the URL into a physical name - but never change a physical name
2463 // physical name may be set if the logical name is changed after construction
2464 if ( aName
.isEmpty() )
2465 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), aName
);
2468 DBG_ASSERT( pSalvageItem
, "Suspicious change of logical name!" );
2473 if ( pSalvageItem
&& pSalvageItem
->GetValue().Len() )
2475 aLogicName
= pSalvageItem
->GetValue();
2477 pImp
->m_bSalvageMode
= sal_True
;
2480 // in case output stream is by mistake here
2481 // clear the reference
2482 SFX_ITEMSET_ARG( pSet
, pOutStreamItem
, SfxUnoAnyItem
, SID_OUTPUTSTREAM
, sal_False
);
2484 && ( !( pOutStreamItem
->GetValue() >>= rOutStream
)
2485 || !aLogicName
.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL
) )
2487 pSet
->ClearItem( SID_OUTPUTSTREAM
);
2488 OSL_FAIL( "Unexpected Output stream parameter!\n" );
2491 if ( aLogicName
.Len() )
2493 // if the logic name is set it should be set in MediaDescriptor as well
2494 SFX_ITEMSET_ARG( pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, sal_False
);
2495 if ( !pFileNameItem
)
2497 // let the ItemSet be created if necessary
2498 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, INetURLObject( aLogicName
).GetMainURL( INetURLObject::NO_DECODE
) ) );
2505 //------------------------------------------------------------------
2506 SfxMedium::SfxMedium()
2507 : IMPL_CTOR( sal_False
, 0 ), // bRoot, pURLObj
2511 pImp(new SfxMedium_Impl( this ))
2516 //------------------------------------------------------------------
2518 void SfxMedium::UseInteractionHandler( sal_Bool bUse
)
2520 pImp
->bAllowDefaultIntHdl
= bUse
;
2523 //------------------------------------------------------------------
2525 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>
2526 SfxMedium::GetInteractionHandler()
2528 // if interaction isnt allowed explicitly ... return empty reference!
2529 if ( !pImp
->bUseInteractionHandler
)
2530 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2532 // search a possible existing handler inside cached item set
2535 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
> xHandler
;
2536 SFX_ITEMSET_ARG( pSet
, pHandler
, SfxUnoAnyItem
, SID_INTERACTIONHANDLER
, sal_False
);
2537 if ( pHandler
&& (pHandler
->GetValue() >>= xHandler
) && xHandler
.is() )
2541 // if default interaction isnt allowed explicitly ... return empty reference!
2542 if ( !pImp
->bAllowDefaultIntHdl
)
2543 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2545 // otherwhise return cached default handler ... if it exist.
2546 if ( pImp
->xInteraction
.is() )
2547 return pImp
->xInteraction
;
2549 // create default handler and cache it!
2550 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> xFactory
= ::comphelper::getProcessServiceFactory();
2551 if ( xFactory
.is() )
2553 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
);
2554 return pImp
->xInteraction
;
2557 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2560 //----------------------------------------------------------------
2562 void SfxMedium::SetFilter( const SfxFilter
* pFilterP
, sal_Bool
/*bResetOrig*/ )
2565 pImp
->nFileVersion
= 0;
2568 //----------------------------------------------------------------
2570 const SfxFilter
* SfxMedium::GetOrigFilter( sal_Bool bNotCurrent
) const
2572 return ( pImp
->pOrigFilter
|| bNotCurrent
) ? pImp
->pOrigFilter
: pFilter
;
2575 //----------------------------------------------------------------
2577 sal_uInt32
SfxMedium::CreatePasswordToModifyHash( const ::rtl::OUString
& aPasswd
, sal_Bool bWriter
)
2579 sal_uInt32 nHash
= 0;
2581 if ( !aPasswd
.isEmpty() )
2585 nHash
= ::comphelper::DocPasswordHelper::GetWordHashAsUINT32( aPasswd
);
2589 rtl_TextEncoding nEncoding
= RTL_TEXTENCODING_UTF8
;
2591 // if the MS-filter should be used
2592 // use the inconsistent algorithm to find the encoding specified by MS
2593 nEncoding
= osl_getThreadTextEncoding();
2596 case RTL_TEXTENCODING_ISO_8859_15
:
2597 case RTL_TEXTENCODING_MS_874
:
2598 case RTL_TEXTENCODING_MS_1250
:
2599 case RTL_TEXTENCODING_MS_1251
:
2600 case RTL_TEXTENCODING_MS_1252
:
2601 case RTL_TEXTENCODING_MS_1253
:
2602 case RTL_TEXTENCODING_MS_1254
:
2603 case RTL_TEXTENCODING_MS_1255
:
2604 case RTL_TEXTENCODING_MS_1256
:
2605 case RTL_TEXTENCODING_MS_1257
:
2606 case RTL_TEXTENCODING_MS_1258
:
2607 case RTL_TEXTENCODING_SHIFT_JIS
:
2608 case RTL_TEXTENCODING_GB_2312
:
2609 case RTL_TEXTENCODING_BIG5
:
2610 // in case the system uses an encoding from the list above, it should be used
2614 // in case other encoding is used, use one of the encodings from the list
2615 nEncoding
= RTL_TEXTENCODING_MS_1250
;
2619 nHash
= ::comphelper::DocPasswordHelper::GetXLHashAsUINT16( aPasswd
, nEncoding
);
2626 //------------------------------------------------------------------
2628 void SfxMedium::Close()
2630 if ( pImp
->xStorage
.is() )
2635 CloseStreams_Impl();
2637 UnlockFile( sal_False
);
2640 void SfxMedium::CloseAndRelease()
2642 if ( pImp
->xStorage
.is() )
2647 CloseAndReleaseStreams_Impl();
2649 UnlockFile( sal_True
);
2652 void SfxMedium::UnlockFile( sal_Bool bReleaseLockStream
)
2654 if ( pImp
->m_xLockingStream
.is() )
2656 if ( bReleaseLockStream
)
2660 uno::Reference
< io::XInputStream
> xInStream
= pImp
->m_xLockingStream
->getInputStream();
2661 uno::Reference
< io::XOutputStream
> xOutStream
= pImp
->m_xLockingStream
->getOutputStream();
2662 if ( xInStream
.is() )
2663 xInStream
->closeInput();
2664 if ( xOutStream
.is() )
2665 xOutStream
->closeOutput();
2667 catch( const uno::Exception
& )
2671 pImp
->m_xLockingStream
= uno::Reference
< io::XStream
>();
2674 if ( pImp
->m_bLocked
)
2678 pImp
->m_bLocked
= sal_False
;
2679 ::svt::DocumentLockFile
aLockFile( aLogicName
);
2680 // TODO/LATER: A warning could be shown in case the file is not the own one
2681 aLockFile
.RemoveFile();
2683 catch( const uno::Exception
& )
2688 void SfxMedium::CloseAndReleaseStreams_Impl()
2690 CloseZipStorage_Impl();
2692 uno::Reference
< io::XInputStream
> xInToClose
= pImp
->xInputStream
;
2693 uno::Reference
< io::XOutputStream
> xOutToClose
;
2694 if ( pImp
->xStream
.is() )
2696 xOutToClose
= pImp
->xStream
->getOutputStream();
2698 // if the locking stream is closed here the related member should be cleaned
2699 if ( pImp
->xStream
== pImp
->m_xLockingStream
)
2700 pImp
->m_xLockingStream
= uno::Reference
< io::XStream
>();
2703 // The probably exsisting SvStream wrappers should be closed first
2704 CloseStreams_Impl();
2706 // in case of salvage mode the storage is based on the streams
2707 if ( !pImp
->m_bSalvageMode
)
2711 if ( xInToClose
.is() )
2712 xInToClose
->closeInput();
2713 if ( xOutToClose
.is() )
2714 xOutToClose
->closeOutput();
2716 catch ( const uno::Exception
& )
2722 //------------------------------------------------------------------
2723 void SfxMedium::CloseStreams_Impl()
2725 CloseInStream_Impl();
2726 CloseOutStream_Impl();
2729 pSet
->ClearItem( SID_CONTENT
);
2731 pImp
->aContent
= ::ucbhelper::Content();
2734 //------------------------------------------------------------------
2736 void SfxMedium::SetIsRemote_Impl()
2738 INetURLObject
aObj( GetName() );
2739 switch( aObj
.GetProtocol() )
2742 case INET_PROT_HTTP
:
2743 case INET_PROT_HTTPS
:
2744 case INET_PROT_POP3
:
2745 case INET_PROT_NEWS
:
2746 case INET_PROT_IMAP
:
2748 bRemote
= sal_True
; break;
2750 bRemote
= ( GetName().CompareToAscii( "private:msgid", 13 ) == COMPARE_EQUAL
);
2754 // As files that are written to the remote transmission must also be able
2757 nStorOpenMode
|= STREAM_READ
;
2762 void SfxMedium::SetName( const String
& aNameP
, sal_Bool bSetOrigURL
)
2764 if( !pImp
->aOrigURL
.Len() )
2765 pImp
->aOrigURL
= aLogicName
;
2767 pImp
->aOrigURL
= aNameP
;
2768 aLogicName
= aNameP
;
2770 pImp
->aContent
= ::ucbhelper::Content();
2774 //----------------------------------------------------------------
2775 const String
& SfxMedium::GetOrigURL() const
2777 return !pImp
->aOrigURL
.Len() ? (String
&)aLogicName
: pImp
->aOrigURL
;
2780 //----------------------------------------------------------------
2782 void SfxMedium::SetPhysicalName_Impl( const rtl::OUString
& rNameP
)
2784 if ( rNameP
!= aName
)
2786 if( pImp
->pTempFile
)
2788 delete pImp
->pTempFile
;
2789 pImp
->pTempFile
= NULL
;
2792 if ( !aName
.isEmpty() || !rNameP
.isEmpty() )
2793 pImp
->aContent
= ::ucbhelper::Content();
2796 bTriedStorage
= sal_False
;
2797 pImp
->bIsStorage
= sal_False
;
2801 //------------------------------------------------------------------
2803 void SfxMedium::ReOpen()
2805 sal_Bool bUseInteractionHandler
= pImp
->bUseInteractionHandler
;
2806 pImp
->bUseInteractionHandler
= sal_False
;
2808 pImp
->bUseInteractionHandler
= bUseInteractionHandler
;
2811 //------------------------------------------------------------------
2813 void SfxMedium::CompleteReOpen()
2815 // do not use temporary file for reopen and in case of success throw the temporary file away
2816 sal_Bool bUseInteractionHandler
= pImp
->bUseInteractionHandler
;
2817 pImp
->bUseInteractionHandler
= sal_False
;
2819 ::utl::TempFile
* pTmpFile
= NULL
;
2820 if ( pImp
->pTempFile
)
2822 pTmpFile
= pImp
->pTempFile
;
2823 pImp
->pTempFile
= NULL
;
2831 if ( pImp
->pTempFile
)
2833 pImp
->pTempFile
->EnableKillingFile( sal_True
);
2834 delete pImp
->pTempFile
;
2836 pImp
->pTempFile
= pTmpFile
;
2837 if ( pImp
->pTempFile
)
2838 aName
= pImp
->pTempFile
->GetFileName();
2842 pTmpFile
->EnableKillingFile( sal_True
);
2847 pImp
->bUseInteractionHandler
= bUseInteractionHandler
;
2850 //------------------------------------------------------------------
2851 SfxMedium::SfxMedium
2853 const String
&rName
, StreamMode nOpenMode
,
2854 const SfxFilter
*pFlt
, SfxItemSet
*pInSet
2856 : IMPL_CTOR( sal_False
, 0 ), // bRoot, pURLObj
2859 pImp(new SfxMedium_Impl( this ))
2862 nStorOpenMode
= nOpenMode
;
2867 SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& aArgs
)
2868 : IMPL_CTOR( sal_False
, 0 ), // bRoot, pURLObj
2871 pImp(new SfxMedium_Impl( this ))
2873 SfxAllItemSet
*pParams
= new SfxAllItemSet( SFX_APP()->GetPool() );
2875 TransformParameters( SID_OPENDOC
, aArgs
, *pParams
);
2878 SFX_ITEMSET_ARG( pSet
, pFilterNameItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
2879 if( pFilterNameItem
)
2880 aFilterName
= pFilterNameItem
->GetValue();
2881 pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4FilterName( aFilterName
);
2883 SFX_ITEMSET_ARG( pSet
, pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, sal_False
);
2886 // QUESTION: there is some treatment of Salvage in Init_Impl; align!
2887 if ( pSalvageItem
->GetValue().Len() )
2889 // if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
2890 // that must be copied here
2892 SFX_ITEMSET_ARG( pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, sal_False
);
2893 if (!pFileNameItem
) throw uno::RuntimeException();
2894 ::rtl::OUString aNewTempFileURL
= SfxMedium::CreateTempCopyWithExt( pFileNameItem
->GetValue() );
2895 if ( !aNewTempFileURL
.isEmpty() )
2897 pSet
->Put( SfxStringItem( SID_FILE_NAME
, aNewTempFileURL
) );
2898 pSet
->ClearItem( SID_INPUTSTREAM
);
2899 pSet
->ClearItem( SID_STREAM
);
2900 pSet
->ClearItem( SID_CONTENT
);
2904 OSL_FAIL( "Can not create a new temporary file for crash recovery!\n" );
2909 SFX_ITEMSET_ARG( pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, sal_False
);
2910 if ( pReadOnlyItem
&& pReadOnlyItem
->GetValue() )
2911 pImp
->m_originallyReadOnly
= true;
2913 SFX_ITEMSET_ARG( pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, sal_False
);
2914 if (!pFileNameItem
) throw uno::RuntimeException();
2915 aLogicName
= pFileNameItem
->GetValue();
2916 nStorOpenMode
= pImp
->m_originallyReadOnly
? SFX_STREAM_READONLY
: SFX_STREAM_READWRITE
;
2921 //------------------------------------------------------------------
2923 SfxMedium::SfxMedium( const uno::Reference
< embed::XStorage
>& rStor
, const String
& rBaseURL
, const SfxItemSet
* p
, sal_Bool bRootP
)
2924 : IMPL_CTOR( bRootP
, 0 ), // bRoot, pURLObj
2926 pImp( new SfxMedium_Impl( this ))
2928 String aType
= SfxFilter::GetTypeFromStorage( rStor
);
2929 pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4EA( aType
);
2930 DBG_ASSERT( pFilter
, "No Filter for storage found!" );
2933 pImp
->xStorage
= rStor
;
2934 pImp
->bDisposeStorage
= sal_False
;
2936 // always take BaseURL first, could be overwritten by ItemSet
2937 GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, rBaseURL
) );
2939 GetItemSet()->Put( *p
);
2942 //------------------------------------------------------------------
2944 SfxMedium::~SfxMedium()
2946 // if there is a requirement to clean the backup this is the last possibility to do it
2953 if( pImp
->bIsTemp
&& !aName
.isEmpty() )
2955 rtl::OUString aTemp
;
2956 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aTemp
))
2958 OSL_FAIL("Physical name not convertable!");
2961 if ( !::utl::UCBContentHelper::Kill( aTemp
) )
2963 OSL_FAIL("Couldn't remove temporary file!");
2973 //----------------------------------------------------------------
2974 const INetURLObject
& SfxMedium::GetURLObject() const
2978 SfxMedium
* pThis
= const_cast < SfxMedium
* > (this);
2979 pThis
->pURLObj
= new INetURLObject( aLogicName
);
2980 if ( pThis
->pURLObj
->HasMark() )
2981 (*pThis
->pURLObj
) = INetURLObject( aLogicName
).GetURLNoMark();
2987 //----------------------------------------------------------------
2989 void SfxMedium::SetReferer( const String
& rRefer
)
2991 pImp
->aReferer
= rRefer
;
2994 //----------------------------------------------------------------
2996 void SfxMedium::SetExpired_Impl( const DateTime
& rDateTime
)
2998 pImp
->aExpireTime
= rDateTime
;
3000 //----------------------------------------------------------------
3002 sal_Bool
SfxMedium::IsExpired() const
3004 return pImp
->aExpireTime
.IsValidAndGregorian() && pImp
->aExpireTime
< DateTime( DateTime::SYSTEM
);
3006 //----------------------------------------------------------------
3008 void SfxMedium::ForceSynchronStream_Impl( sal_Bool bForce
)
3012 SvLockBytes
* pBytes
= pInStream
->GetLockBytes();
3014 pBytes
->SetSynchronMode( bForce
);
3016 pImp
->bForceSynchron
= bForce
;
3019 //----------------------------------------------------------------
3020 SfxFrame
* SfxMedium::GetLoadTargetFrame() const
3022 return pImp
->wLoadTargetFrame
;
3024 //----------------------------------------------------------------
3026 void SfxMedium::SetLoadTargetFrame(SfxFrame
* pFrame
)
3028 pImp
->wLoadTargetFrame
= pFrame
;
3030 //----------------------------------------------------------------
3032 void SfxMedium::SetStorage_Impl( const uno::Reference
< embed::XStorage
>& rStor
)
3034 pImp
->xStorage
= rStor
;
3036 //----------------------------------------------------------------
3038 SfxItemSet
* SfxMedium::GetItemSet() const
3040 // this method *must* return an ItemSet, returning NULL can cause crashes
3042 ((SfxMedium
*)this)->pSet
= new SfxAllItemSet( SFX_APP()->GetPool() );
3045 //----------------------------------------------------------------
3047 SvKeyValueIterator
* SfxMedium::GetHeaderAttributes_Impl()
3049 if( !pImp
->xAttributes
.Is() )
3051 pImp
->xAttributes
= SvKeyValueIteratorRef( new SvKeyValueIterator
);
3053 if ( GetContent().is() )
3055 pImp
->bIsCharsetInitialized
= sal_True
;
3059 Any aAny
= pImp
->aContent
.getPropertyValue( ::rtl::OUString("MediaType") );
3060 ::rtl::OUString aContentType
;
3061 aAny
>>= aContentType
;
3063 pImp
->xAttributes
->Append( SvKeyValue( ::rtl::OUString("content-type"), aContentType
) );
3065 catch ( const ::com::sun::star::uno::Exception
& )
3071 return pImp
->xAttributes
;
3074 ::com::sun::star::uno::Reference
< ::com::sun::star::io::XInputStream
> SfxMedium::GetInputStream()
3076 if ( !pImp
->xInputStream
.is() )
3078 return pImp
->xInputStream
;
3081 const uno::Sequence
< util::RevisionTag
>& SfxMedium::GetVersionList( bool _bNoReload
)
3083 // if the medium has no name, then this medium should represent a new document and can have no version info
3084 if ( ( !_bNoReload
|| !pImp
->m_bVersionsAlreadyLoaded
) && !pImp
->aVersions
.getLength() &&
3085 ( !aName
.isEmpty() || aLogicName
.Len() ) && GetStorage().is() )
3087 uno::Reference
< document::XDocumentRevisionListPersistence
> xReader( comphelper::getProcessServiceFactory()->createInstance(
3088 ::rtl::OUString("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY
);
3093 pImp
->aVersions
= xReader
->load( GetStorage() );
3095 catch ( const uno::Exception
& )
3101 if ( !pImp
->m_bVersionsAlreadyLoaded
)
3102 pImp
->m_bVersionsAlreadyLoaded
= sal_True
;
3104 return pImp
->aVersions
;
3107 uno::Sequence
< util::RevisionTag
> SfxMedium::GetVersionList( const uno::Reference
< embed::XStorage
>& xStorage
)
3109 uno::Reference
< document::XDocumentRevisionListPersistence
> xReader( comphelper::getProcessServiceFactory()->createInstance(
3110 ::rtl::OUString("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY
);
3115 return xReader
->load( xStorage
);
3117 catch ( const uno::Exception
& )
3122 return uno::Sequence
< util::RevisionTag
>();
3125 sal_uInt16
SfxMedium::AddVersion_Impl( util::RevisionTag
& rRevision
)
3127 if ( GetStorage().is() )
3129 // To determine a unique name for the stream
3130 std::vector
<sal_uInt32
> aLongs
;
3131 sal_Int32 nLength
= pImp
->aVersions
.getLength();
3132 for ( sal_Int32 m
=0; m
<nLength
; m
++ )
3134 sal_uInt32 nVer
= static_cast<sal_uInt32
>(String( pImp
->aVersions
[m
].Identifier
).Copy(7).ToInt32());
3136 for ( n
=0; n
<aLongs
.size(); ++n
)
3137 if ( nVer
<aLongs
[n
] )
3140 aLongs
.insert( aLongs
.begin()+n
, nVer
);
3144 for ( nKey
=0; nKey
<aLongs
.size(); ++nKey
)
3145 if ( aLongs
[nKey
] > ( sal_uIntPtr
) nKey
+1 )
3148 String aRevName
= DEFINE_CONST_UNICODE( "Version" );
3149 aRevName
+= String::CreateFromInt32( nKey
+ 1 );
3150 pImp
->aVersions
.realloc( nLength
+1 );
3151 rRevision
.Identifier
= aRevName
;
3152 pImp
->aVersions
[nLength
] = rRevision
;
3159 sal_Bool
SfxMedium::RemoveVersion_Impl( const ::rtl::OUString
& rName
)
3161 if ( !pImp
->aVersions
.getLength() )
3164 sal_Int32 nLength
= pImp
->aVersions
.getLength();
3165 for ( sal_Int32 n
=0; n
<nLength
; n
++ )
3167 if ( pImp
->aVersions
[n
].Identifier
== rName
)
3169 for ( sal_Int32 m
=n
; m
<nLength
-1; m
++ )
3170 pImp
->aVersions
[m
] = pImp
->aVersions
[m
+1];
3171 pImp
->aVersions
.realloc(nLength
-1);
3179 sal_Bool
SfxMedium::TransferVersionList_Impl( SfxMedium
& rMedium
)
3181 if ( rMedium
.pImp
->aVersions
.getLength() )
3183 pImp
->aVersions
= rMedium
.pImp
->aVersions
;
3190 sal_Bool
SfxMedium::SaveVersionList_Impl( sal_Bool
/*bUseXML*/ )
3192 if ( GetStorage().is() )
3194 if ( !pImp
->aVersions
.getLength() )
3197 uno::Reference
< document::XDocumentRevisionListPersistence
> xWriter( comphelper::getProcessServiceFactory()->createInstance(
3198 ::rtl::OUString("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY
);
3203 xWriter
->store( GetStorage(), pImp
->aVersions
);
3206 catch ( const uno::Exception
& )
3215 //----------------------------------------------------------------
3216 sal_Bool
SfxMedium::IsReadOnly()
3218 sal_Bool bReadOnly
= sal_False
;
3220 // a) ReadOnly filter cant produce read/write contents!
3223 ((pFilter
->GetFilterFlags() & SFX_FILTER_OPENREADONLY
) == SFX_FILTER_OPENREADONLY
)
3226 // b) if filter allow read/write contents .. check open mode of the storage
3228 bReadOnly
= !( GetOpenMode() & STREAM_WRITE
);
3230 // c) the API can force the readonly state!
3233 SFX_ITEMSET_ARG( GetItemSet(), pItem
, SfxBoolItem
, SID_DOC_READONLY
, sal_False
);
3235 bReadOnly
= pItem
->GetValue();
3241 bool SfxMedium::IsOriginallyReadOnly() const
3243 return pImp
->m_originallyReadOnly
;
3246 //----------------------------------------------------------------
3247 sal_Bool
SfxMedium::SetWritableForUserOnly( const ::rtl::OUString
& aURL
)
3249 // UCB does not allow to allow write access only for the user,
3251 sal_Bool bResult
= sal_False
;
3253 ::osl::DirectoryItem aDirItem
;
3254 if ( ::osl::DirectoryItem::get( aURL
, aDirItem
) == ::osl::FileBase::E_None
)
3256 ::osl::FileStatus
aFileStatus( osl_FileStatus_Mask_Attributes
);
3257 if ( aDirItem
.getFileStatus( aFileStatus
) == osl::FileBase::E_None
3258 && aFileStatus
.isValid( osl_FileStatus_Mask_Attributes
) )
3260 sal_uInt64 nAttributes
= aFileStatus
.getAttributes();
3262 nAttributes
&= ~(osl_File_Attribute_OwnWrite
|
3263 osl_File_Attribute_GrpWrite
|
3264 osl_File_Attribute_OthWrite
|
3265 osl_File_Attribute_ReadOnly
);
3266 nAttributes
|= (osl_File_Attribute_OwnWrite
|
3267 osl_File_Attribute_OwnRead
);
3269 bResult
= ( osl::File::setAttributes( aURL
, nAttributes
) == ::osl::FileBase::E_None
);
3276 //----------------------------------------------------------------
3277 void SfxMedium::CreateTempFile( sal_Bool bReplace
)
3279 if ( pImp
->pTempFile
)
3284 DELETEZ( pImp
->pTempFile
);
3288 pImp
->pTempFile
= new ::utl::TempFile();
3289 pImp
->pTempFile
->EnableKillingFile( sal_True
);
3290 aName
= pImp
->pTempFile
->GetFileName();
3291 ::rtl::OUString aTmpURL
= pImp
->pTempFile
->GetURL();
3292 if ( aName
.isEmpty() || aTmpURL
.isEmpty() )
3294 SetError( ERRCODE_IO_CANTWRITE
, ::rtl::OUString( OSL_LOG_PREFIX
) );
3298 if ( !( nStorOpenMode
& STREAM_TRUNC
) )
3300 sal_Bool bTransferSuccess
= sal_False
;
3302 if ( GetContent().is()
3303 && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
3304 && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
3306 // if there is already such a document, we should copy it
3307 // if it is a file system use OS copy process
3310 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
3311 INetURLObject
aTmpURLObj( aTmpURL
);
3312 ::rtl::OUString aFileName
= aTmpURLObj
.getName( INetURLObject::LAST_SEGMENT
,
3314 INetURLObject::DECODE_WITH_CHARSET
);
3315 if ( !aFileName
.isEmpty() && aTmpURLObj
.removeSegment() )
3317 ::ucbhelper::Content
aTargetContent( aTmpURLObj
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
3318 if ( aTargetContent
.transferContent( pImp
->aContent
, ::ucbhelper::InsertOperation_COPY
, aFileName
, NameClash::OVERWRITE
) )
3320 SetWritableForUserOnly( aTmpURL
);
3321 bTransferSuccess
= sal_True
;
3325 catch( const uno::Exception
& )
3328 if ( bTransferSuccess
)
3335 if ( !bTransferSuccess
&& pInStream
)
3337 // the case when there is no URL-access available or this is a remote protocoll
3338 // but there is an input stream
3342 char *pBuf
= new char [8192];
3343 sal_uInt32 nErr
= ERRCODE_NONE
;
3346 pOutStream
->Seek(0);
3348 while( !pInStream
->IsEof() && nErr
== ERRCODE_NONE
)
3350 sal_uInt32 nRead
= pInStream
->Read( pBuf
, 8192 );
3351 nErr
= pInStream
->GetError();
3352 pOutStream
->Write( pBuf
, nRead
);
3355 bTransferSuccess
= sal_True
;
3359 CloseOutStream_Impl();
3363 // Quite strange design, but currently it is expected that in this case no transfer happens
3364 // TODO/LATER: get rid of this inconsistent part of the call design
3365 bTransferSuccess
= sal_True
;
3369 if ( !bTransferSuccess
)
3371 SetError( ERRCODE_IO_CANTWRITE
, ::rtl::OUString( OSL_LOG_PREFIX
) );
3379 //----------------------------------------------------------------
3380 void SfxMedium::CreateTempFileNoCopy()
3382 // this call always replaces the existing temporary file
3383 if ( pImp
->pTempFile
)
3384 delete pImp
->pTempFile
;
3386 pImp
->pTempFile
= new ::utl::TempFile();
3387 pImp
->pTempFile
->EnableKillingFile( sal_True
);
3388 aName
= pImp
->pTempFile
->GetFileName();
3389 if ( aName
.isEmpty() )
3391 SetError( ERRCODE_IO_CANTWRITE
, ::rtl::OUString( OSL_LOG_PREFIX
) );
3395 CloseOutStream_Impl();
3399 void SfxMedium::SetCharset( ::rtl::OUString aChs
)
3401 pImp
->bIsCharsetInitialized
= sal_True
;
3402 pImp
->aCharset
= aChs
;
3405 sal_Bool
SfxMedium::SignContents_Impl( sal_Bool bScriptingContent
, const ::rtl::OUString
& aODFVersion
, sal_Bool bHasValidDocumentSignature
)
3407 sal_Bool bChanges
= sal_False
;
3409 // the medium should be closed to be able to sign, the caller is responsible to close it
3410 if ( !IsOpen() && !GetError() )
3412 // The component should know if there was a valid document signature, since
3413 // it should show a warning in this case
3414 uno::Sequence
< uno::Any
> aArgs( 2 );
3415 aArgs
[0] <<= aODFVersion
;
3416 aArgs
[1] <<= bHasValidDocumentSignature
;
3417 ::com::sun::star::uno::Reference
< ::com::sun::star::security::XDocumentDigitalSignatures
> xSigner(
3418 comphelper::getProcessServiceFactory()->createInstanceWithArguments(
3419 rtl::OUString( "com.sun.star.security.DocumentDigitalSignatures" ),
3421 ::com::sun::star::uno::UNO_QUERY
);
3425 uno::Reference
< embed::XStorage
> xWriteableZipStor
;
3426 if ( !IsReadOnly() )
3428 // we can reuse the temporary file if there is one already
3429 CreateTempFile( sal_False
);
3434 if ( !pImp
->xStream
.is() )
3435 throw uno::RuntimeException();
3437 xWriteableZipStor
= ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xStream
);
3438 if ( !xWriteableZipStor
.is() )
3439 throw uno::RuntimeException();
3441 uno::Reference
< embed::XStorage
> xMetaInf
= xWriteableZipStor
->openStorageElement(
3442 ::rtl::OUString( "META-INF" ),
3443 embed::ElementModes::READWRITE
);
3444 if ( !xMetaInf
.is() )
3445 throw uno::RuntimeException();
3447 if ( bScriptingContent
)
3449 // If the signature has already the document signature it will be removed
3450 // after the scripting signature is inserted.
3451 uno::Reference
< io::XStream
> xStream(
3452 xMetaInf
->openStreamElement( xSigner
->getScriptingContentSignatureDefaultStreamName(),
3453 embed::ElementModes::READWRITE
),
3454 uno::UNO_SET_THROW
);
3456 if ( xSigner
->signScriptingContent( GetZipStorageToSign_Impl(), xStream
) )
3458 // remove the document signature if any
3459 ::rtl::OUString aDocSigName
= xSigner
->getDocumentContentSignatureDefaultStreamName();
3460 if ( !aDocSigName
.isEmpty() && xMetaInf
->hasByName( aDocSigName
) )
3461 xMetaInf
->removeElement( aDocSigName
);
3463 uno::Reference
< embed::XTransactedObject
> xTransact( xMetaInf
, uno::UNO_QUERY_THROW
);
3464 xTransact
->commit();
3465 xTransact
.set( xWriteableZipStor
, uno::UNO_QUERY_THROW
);
3466 xTransact
->commit();
3468 // the temporary file has been written, commit it to the original file
3470 bChanges
= sal_True
;
3475 uno::Reference
< io::XStream
> xStream(
3476 xMetaInf
->openStreamElement( xSigner
->getDocumentContentSignatureDefaultStreamName(),
3477 embed::ElementModes::READWRITE
),
3478 uno::UNO_SET_THROW
);
3480 if ( xSigner
->signDocumentContent( GetZipStorageToSign_Impl(), xStream
) )
3482 uno::Reference
< embed::XTransactedObject
> xTransact( xMetaInf
, uno::UNO_QUERY_THROW
);
3483 xTransact
->commit();
3484 xTransact
.set( xWriteableZipStor
, uno::UNO_QUERY_THROW
);
3485 xTransact
->commit();
3487 // the temporary file has been written, commit it to the original file
3489 bChanges
= sal_True
;
3493 catch ( const uno::Exception
& )
3495 OSL_FAIL( "Couldn't use signing functionality!\n" );
3504 if ( bScriptingContent
)
3505 xSigner
->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference
< io::XInputStream
>() );
3507 xSigner
->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference
< io::XInputStream
>() );
3509 catch( const uno::Exception
& )
3511 OSL_FAIL( "Couldn't use signing functionality!\n" );
3522 //----------------------------------------------------------------
3523 sal_uInt16
SfxMedium::GetCachedSignatureState_Impl()
3525 return pImp
->m_nSignatureState
;
3528 //----------------------------------------------------------------
3529 void SfxMedium::SetCachedSignatureState_Impl( sal_uInt16 nState
)
3531 pImp
->m_nSignatureState
= nState
;
3534 sal_Bool
SfxMedium::HasStorage_Impl() const
3536 return pImp
->xStorage
.is();
3539 sal_Bool
SfxMedium::IsOpen() const
3541 return pInStream
|| pOutStream
|| pImp
->xStorage
.is();
3544 ::rtl::OUString
SfxMedium::CreateTempCopyWithExt( const ::rtl::OUString
& aURL
)
3546 ::rtl::OUString aResult
;
3548 if ( !aURL
.isEmpty() )
3550 sal_Int32 nPrefixLen
= aURL
.lastIndexOf( '.' );
3551 String aExt
= ( nPrefixLen
== -1 ) ? String() : String( aURL
.copy( nPrefixLen
) );
3553 ::rtl::OUString aNewTempFileURL
= ::utl::TempFile( String(), &aExt
).GetURL();
3554 if ( !aNewTempFileURL
.isEmpty() )
3556 INetURLObject
aSource( aURL
);
3557 INetURLObject
aDest( aNewTempFileURL
);
3558 ::rtl::OUString aFileName
= aDest
.getName( INetURLObject::LAST_SEGMENT
,
3560 INetURLObject::DECODE_WITH_CHARSET
);
3561 if ( !aFileName
.isEmpty() && aDest
.removeSegment() )
3565 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
3566 ::ucbhelper::Content
aTargetContent( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
3567 ::ucbhelper::Content
aSourceContent( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
3568 if ( aTargetContent
.transferContent( aSourceContent
,
3569 ::ucbhelper::InsertOperation_COPY
,
3571 NameClash::OVERWRITE
) )
3574 aResult
= aNewTempFileURL
;
3577 catch( const uno::Exception
& )
3586 sal_Bool
SfxMedium::CallApproveHandler( const uno::Reference
< task::XInteractionHandler
>& xHandler
, uno::Any aRequest
, sal_Bool bAllowAbort
)
3588 sal_Bool bResult
= sal_False
;
3590 if ( xHandler
.is() )
3594 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( bAllowAbort
? 2 : 1 );
3596 ::rtl::Reference
< ::comphelper::OInteractionApprove
> pApprove( new ::comphelper::OInteractionApprove
);
3597 aContinuations
[ 0 ] = pApprove
.get();
3601 ::rtl::Reference
< ::comphelper::OInteractionAbort
> pAbort( new ::comphelper::OInteractionAbort
);
3602 aContinuations
[ 1 ] = pAbort
.get();
3605 xHandler
->handle(::framework::InteractionRequest::CreateRequest (aRequest
,aContinuations
));
3606 bResult
= pApprove
->wasSelected();
3608 catch( const Exception
& )
3616 ::rtl::OUString
SfxMedium::SwitchDocumentToTempFile()
3618 // the method returns empty string in case of failure
3619 ::rtl::OUString aResult
;
3620 ::rtl::OUString aOrigURL
= aLogicName
;
3622 if ( !aOrigURL
.isEmpty() )
3624 sal_Int32 nPrefixLen
= aOrigURL
.lastIndexOf( '.' );
3625 String aExt
= ( nPrefixLen
== -1 ) ? String() : String( aOrigURL
.copy( nPrefixLen
) );
3626 ::rtl::OUString aNewURL
= ::utl::TempFile( String(), &aExt
).GetURL();
3628 // TODO/LATER: In future the aLogicName should be set to shared folder URL
3629 // and a temporary file should be created. Transport_Impl should be impossible then.
3630 if ( !aNewURL
.isEmpty() )
3632 uno::Reference
< embed::XStorage
> xStorage
= GetStorage();
3633 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY
);
3635 if ( xOptStorage
.is() )
3637 // TODO/LATER: reuse the pImp->pTempFile if it already exists
3638 CanDisposeStorage_Impl( sal_False
);
3640 SetPhysicalName_Impl( String() );
3643 // remove the readonly state
3644 sal_Bool bWasReadonly
= sal_False
;
3645 nStorOpenMode
= SFX_STREAM_READWRITE
;
3646 SFX_ITEMSET_ARG( pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, sal_False
);
3647 if ( pReadOnlyItem
&& pReadOnlyItem
->GetValue() )
3648 bWasReadonly
= sal_True
;
3649 GetItemSet()->ClearItem( SID_DOC_READONLY
);
3652 LockOrigFileOnDemand( sal_False
, sal_False
);
3653 CreateTempFile( sal_True
);
3656 if ( pImp
->xStream
.is() )
3660 xOptStorage
->writeAndAttachToStream( pImp
->xStream
);
3661 pImp
->xStorage
= xStorage
;
3664 catch( const uno::Exception
& )
3668 if ( aResult
.isEmpty() )
3671 SetPhysicalName_Impl( String() );
3672 SetName( aOrigURL
);
3675 // set the readonly state back
3676 nStorOpenMode
= SFX_STREAM_READONLY
;
3677 GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY
, sal_True
));
3680 pImp
->xStorage
= xStorage
;
3689 sal_Bool
SfxMedium::SwitchDocumentToFile( ::rtl::OUString aURL
)
3691 // the method is only for storage based documents
3692 sal_Bool bResult
= sal_False
;
3693 ::rtl::OUString aOrigURL
= aLogicName
;
3695 if ( !aURL
.isEmpty() && !aOrigURL
.isEmpty() )
3697 uno::Reference
< embed::XStorage
> xStorage
= GetStorage();
3698 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY
);
3700 if ( xOptStorage
.is() )
3702 // TODO/LATER: reuse the pImp->pTempFile if it already exists
3703 CanDisposeStorage_Impl( sal_False
);
3705 SetPhysicalName_Impl( String() );
3708 // open the temporary file based document
3710 LockOrigFileOnDemand( sal_False
, sal_False
);
3711 CreateTempFile( sal_True
);
3714 if ( pImp
->xStream
.is() )
3718 uno::Reference
< io::XTruncate
> xTruncate( pImp
->xStream
, uno::UNO_QUERY_THROW
);
3719 if ( xTruncate
.is() )
3720 xTruncate
->truncate();
3722 xOptStorage
->writeAndAttachToStream( pImp
->xStream
);
3723 pImp
->xStorage
= xStorage
;
3726 catch( const uno::Exception
& )
3733 SetPhysicalName_Impl( String() );
3734 SetName( aOrigURL
);
3736 pImp
->xStorage
= xStorage
;
3744 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */