1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <sfx2/docfile.hxx>
23 #include "sfx2/signaturestate.hxx"
25 #include <uno/mapping.hxx>
26 #include <com/sun/star/task/InteractionHandler.hpp>
27 #include <com/sun/star/uno/Reference.h>
28 #include <com/sun/star/ucb/XContent.hpp>
29 #include <com/sun/star/container/XChild.hpp>
30 #include <com/sun/star/document/XDocumentRevisionListPersistence.hpp>
31 #include <com/sun/star/document/LockedDocumentRequest.hpp>
32 #include <com/sun/star/document/OwnLockOnDocumentRequest.hpp>
33 #include <com/sun/star/document/LockedOnSavingRequest.hpp>
34 #include <com/sun/star/document/LockFileIgnoreRequest.hpp>
35 #include <com/sun/star/document/ChangedByOthersRequest.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/embed/XTransactedObject.hpp>
38 #include <com/sun/star/embed/ElementModes.hpp>
39 #include <com/sun/star/embed/UseBackupException.hpp>
40 #include <com/sun/star/embed/XOptimizedStorage.hpp>
41 #include <com/sun/star/ucb/InteractiveIOException.hpp>
42 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
43 #include <com/sun/star/ucb/CommandFailedException.hpp>
44 #include <com/sun/star/ucb/CommandAbortedException.hpp>
45 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
46 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
47 #include <com/sun/star/ucb/XContentProvider.hpp>
48 #include <com/sun/star/ucb/XProgressHandler.hpp>
49 #include <com/sun/star/ucb/XCommandInfo.hpp>
50 #include <com/sun/star/io/XOutputStream.hpp>
51 #include <com/sun/star/io/XInputStream.hpp>
52 #include <com/sun/star/io/XTruncate.hpp>
53 #include <com/sun/star/io/XStreamListener.hpp>
54 #include <com/sun/star/io/XSeekable.hpp>
55 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
56 #include <com/sun/star/lang/XInitialization.hpp>
57 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
58 #include <com/sun/star/ucb/NameClash.hpp>
59 #include <com/sun/star/ucb/TransferInfo.hpp>
60 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
61 #include <com/sun/star/ucb/OpenMode.hpp>
62 #include <com/sun/star/logging/DocumentIOLogRing.hpp>
63 #include <com/sun/star/logging/XSimpleLogRing.hpp>
64 #include <cppuhelper/implbase1.hxx>
65 #include <com/sun/star/beans/PropertyValue.hpp>
66 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
67 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
68 #include <tools/urlobj.hxx>
69 #include <unotools/tempfile.hxx>
70 #include <comphelper/processfactory.hxx>
71 #include <comphelper/componentcontext.hxx>
72 #include <comphelper/interaction.hxx>
73 #include <framework/interaction.hxx>
74 #include <unotools/streamhelper.hxx>
75 #include <unotools/localedatawrapper.hxx>
76 #include <vcl/msgbox.hxx>
77 #include <svl/stritem.hxx>
78 #include <svl/eitem.hxx>
79 #include <svl/lckbitem.hxx>
80 #include <svtools/sfxecode.hxx>
81 #include <svl/itemset.hxx>
82 #include <svl/intitem.hxx>
83 #include <svtools/svparser.hxx> // SvKeyValue
84 #include <cppuhelper/weakref.hxx>
86 #include <unotools/streamwrap.hxx>
88 #include <rtl/logfile.hxx>
89 #include <osl/file.hxx>
91 #include <comphelper/storagehelper.hxx>
92 #include <comphelper/mediadescriptor.hxx>
93 #include <comphelper/configurationhelper.hxx>
94 #include <comphelper/docpasswordhelper.hxx>
95 #include <tools/inetmime.hxx>
96 #include <unotools/ucblockbytes.hxx>
97 #include <unotools/pathoptions.hxx>
98 #include <svtools/asynclink.hxx>
99 #include <svl/inettype.hxx>
100 #include <ucbhelper/commandenvironment.hxx>
101 #include <unotools/localfilehelper.hxx>
102 #include <unotools/ucbstreamhelper.hxx>
103 #include <unotools/ucbhelper.hxx>
104 #include <unotools/progresshandlerwrap.hxx>
105 #include <ucbhelper/content.hxx>
106 #include <ucbhelper/interactionrequest.hxx>
107 #include <sot/stg.hxx>
108 #include <unotools/saveopt.hxx>
109 #include <svl/documentlockfile.hxx>
110 #include <com/sun/star/document/DocumentRevisionListPersistence.hpp>
112 #include "helper.hxx"
113 #include <sfx2/request.hxx> // SFX_ITEMSET_SET
114 #include <sfx2/app.hxx> // GetFilterMatcher
115 #include <sfx2/frame.hxx> // LoadTargetFrame
116 #include "fltfnc.hxx" // SfxFilterMatcher
117 #include <sfx2/docfilt.hxx> // SfxFilter
118 #include <sfx2/objsh.hxx> // CheckOpenMode
119 #include <sfx2/docfac.hxx> // GetFilterContainer
121 #include "openflag.hxx" // SFX_STREAM_READONLY etc.
122 #include "sfx2/sfxresid.hxx"
123 #include <sfx2/appuno.hxx>
124 #include "sfxacldetect.hxx"
125 #include "officecfg/Office/Common.hxx"
127 #include <boost/noncopyable.hpp>
128 #include <boost/scoped_ptr.hpp>
130 using namespace ::com::sun::star
;
131 using namespace ::com::sun::star::uno
;
132 using namespace ::com::sun::star::ucb
;
133 using namespace ::com::sun::star::beans
;
134 using namespace ::com::sun::star::io
;
138 static const sal_Int8 LOCK_UI_NOLOCK
= 0;
139 static const sal_Int8 LOCK_UI_SUCCEEDED
= 1;
140 static const sal_Int8 LOCK_UI_TRY
= 2;
142 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
144 bool IsSystemFileLockingUsed()
146 // check whether system file locking has been used, the default value is false
147 bool bUseSystemLock
= false;
151 uno::Reference
< uno::XInterface
> xCommonConfig
= ::comphelper::ConfigurationHelper::openConfig(
152 ::comphelper::getProcessComponentContext(),
153 OUString( "/org.openoffice.Office.Common" ),
154 ::comphelper::ConfigurationHelper::E_STANDARD
);
155 if ( !xCommonConfig
.is() )
156 throw uno::RuntimeException();
158 ::comphelper::ConfigurationHelper::readRelativeKey(
161 OUString( "UseDocumentSystemFileLocking" ) ) >>= bUseSystemLock
;
163 catch( const uno::Exception
& )
167 return bUseSystemLock
;
170 //----------------------------------------------------------------
171 bool IsOOoLockFileUsed()
173 // check whether system file locking has been used, the default value is false
174 bool bOOoLockFileUsed
= false;
178 uno::Reference
< uno::XInterface
> xCommonConfig
= ::comphelper::ConfigurationHelper::openConfig(
179 ::comphelper::getProcessComponentContext(),
180 OUString( "/org.openoffice.Office.Common" ),
181 ::comphelper::ConfigurationHelper::E_STANDARD
);
182 if ( !xCommonConfig
.is() )
183 throw uno::RuntimeException();
185 ::comphelper::ConfigurationHelper::readRelativeKey(
188 OUString( "UseDocumentOOoLockFile" ) ) >>= bOOoLockFileUsed
;
190 catch( const uno::Exception
& )
194 return bOOoLockFileUsed
;
199 return officecfg::Office::Common::Misc::UseLocking::get();
204 } // anonymous namespace
205 //==========================================================
208 //----------------------------------------------------------------
209 class SfxMediumHandler_Impl
: public ::cppu::WeakImplHelper1
< com::sun::star::task::XInteractionHandler
>
211 com::sun::star::uno::Reference
< com::sun::star::task::XInteractionHandler
> m_xInter
;
214 virtual void SAL_CALL
handle( const com::sun::star::uno::Reference
< com::sun::star::task::XInteractionRequest
>& xRequest
)
215 throw( com::sun::star::uno::RuntimeException
);
217 SfxMediumHandler_Impl( com::sun::star::uno::Reference
< com::sun::star::task::XInteractionHandler
> xInteraction
)
218 : m_xInter( xInteraction
)
221 ~SfxMediumHandler_Impl();
224 //----------------------------------------------------------------
225 SfxMediumHandler_Impl::~SfxMediumHandler_Impl()
229 //----------------------------------------------------------------
230 void SAL_CALL
SfxMediumHandler_Impl::handle( const com::sun::star::uno::Reference
< com::sun::star::task::XInteractionRequest
>& xRequest
)
231 throw( com::sun::star::uno::RuntimeException
)
236 com::sun::star::uno::Any aRequest
= xRequest
->getRequest();
237 com::sun::star::ucb::InteractiveIOException aIoException
;
238 com::sun::star::ucb::UnsupportedDataSinkException aSinkException
;
239 if ( (aRequest
>>= aIoException
) && ( aIoException
.Code
== IOErrorCode_ACCESS_DENIED
|| aIoException
.Code
== IOErrorCode_LOCKING_VIOLATION
) )
242 if ( aRequest
>>= aSinkException
)
245 m_xInter
->handle( xRequest
);
248 class SfxMedium_Impl
: boost::noncopyable
251 StreamMode m_nStorOpenMode
;
254 ::ucbhelper::Content aContent
;
255 bool bUpdatePickList
:1;
257 bool bDownloadDone
:1;
259 bool bUseInteractionHandler
:1;
260 bool bAllowDefaultIntHdl
:1;
261 bool bDisposeStorage
:1;
262 bool bStorageBasedOnInStream
:1;
263 bool m_bSalvageMode
:1;
264 bool m_bVersionsAlreadyLoaded
:1;
266 bool m_bGotDateTime
:1;
267 bool m_bRemoveBackup
:1;
268 bool m_bOriginallyReadOnly
:1;
269 bool m_bTriedStorage
:1;
271 bool m_bInputStreamIsReadOnly
:1;
275 OUString m_aLogicName
;
276 OUString m_aLongName
;
278 mutable SfxItemSet
* m_pSet
;
279 mutable INetURLObject
* m_pURLObj
;
281 const SfxFilter
* m_pFilter
;
282 boost::scoped_ptr
<SfxFilter
> m_pCustomFilter
;
284 SfxMedium
* pAntiImpl
;
285 SvStream
* m_pInStream
;
286 SvStream
* m_pOutStream
;
288 const SfxFilter
* pOrigFilter
;
290 DateTime aExpireTime
;
291 SfxFrameWeak wLoadTargetFrame
;
292 SvKeyValueIteratorRef xAttributes
;
294 svtools::AsynchronLink aDoneLink
;
296 uno::Sequence
< util::RevisionTag
> aVersions
;
298 ::utl::TempFile
* pTempFile
;
300 uno::Reference
<embed::XStorage
> xStorage
;
301 uno::Reference
<embed::XStorage
> m_xZipStorage
;
302 uno::Reference
<io::XInputStream
> m_xInputStreamToLoadFrom
;
303 uno::Reference
<io::XInputStream
> xInputStream
;
304 uno::Reference
<io::XStream
> xStream
;
305 uno::Reference
<io::XStream
> m_xLockingStream
;
306 uno::Reference
<task::XInteractionHandler
> xInteraction
;
307 uno::Reference
<logging::XSimpleLogRing
> m_xLogRing
;
309 sal_uInt32 nLastStorageError
;
311 OUString m_aBackupURL
;
313 // the following member is changed and makes sense only during saving
314 // TODO/LATER: in future the signature state should be controlled by the medium not by the document
315 // in this case the member will hold this information
316 sal_uInt16 m_nSignatureState
;
318 util::DateTime m_aDateTime
;
320 SfxMedium_Impl( SfxMedium
* pAntiImplP
);
323 OUString
getFilterMimeType()
324 { return m_pFilter
== 0 ? OUString() : m_pFilter
->GetMimeType(); }
327 //------------------------------------------------------------------
328 SfxMedium_Impl::SfxMedium_Impl( SfxMedium
* pAntiImplP
) :
329 m_nStorOpenMode(SFX_STREAM_READWRITE
),
330 m_eError(SVSTREAM_OK
),
331 bUpdatePickList(true),
333 bDownloadDone( true ),
335 bUseInteractionHandler( true ),
336 bAllowDefaultIntHdl( false ),
337 bDisposeStorage( false ),
338 bStorageBasedOnInStream( false ),
339 m_bSalvageMode( false ),
340 m_bVersionsAlreadyLoaded( false ),
342 m_bGotDateTime( false ),
343 m_bRemoveBackup( false ),
344 m_bOriginallyReadOnly(false),
345 m_bTriedStorage(false),
347 m_bInputStreamIsReadOnly(false),
352 pAntiImpl( pAntiImplP
),
356 aExpireTime( Date( Date::SYSTEM
) + 10, Time( Time::SYSTEM
) ),
358 nLastStorageError( 0 ),
359 m_nSignatureState( SIGNATURESTATE_NOSIGNATURES
)
361 aDoneLink
.CreateMutex();
364 //------------------------------------------------------------------
365 SfxMedium_Impl::~SfxMedium_Impl()
367 aDoneLink
.ClearPendingCall();
374 void SfxMedium::ResetError()
376 pImp
->m_eError
= SVSTREAM_OK
;
377 if( pImp
->m_pInStream
)
378 pImp
->m_pInStream
->ResetError();
379 if( pImp
->m_pOutStream
)
380 pImp
->m_pOutStream
->ResetError();
383 //------------------------------------------------------------------
384 sal_uInt32
SfxMedium::GetLastStorageCreationState()
386 return pImp
->nLastStorageError
;
389 //------------------------------------------------------------------
390 void SfxMedium::AddLog( const OUString
& aMessage
)
392 if ( !pImp
->m_xLogRing
.is() )
396 Reference
<XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
397 pImp
->m_xLogRing
.set( logging::DocumentIOLogRing::get(xContext
) );
399 catch( const uno::Exception
& )
403 if ( pImp
->m_xLogRing
.is() )
404 pImp
->m_xLogRing
->logString( aMessage
);
407 //------------------------------------------------------------------
408 void SfxMedium::SetError( sal_uInt32 nError
, const OUString
& aLogMessage
)
410 pImp
->m_eError
= nError
;
411 if ( pImp
->m_eError
!= ERRCODE_NONE
&& !aLogMessage
.isEmpty() )
412 AddLog( aLogMessage
);
415 //------------------------------------------------------------------
416 sal_uInt32
SfxMedium::GetErrorCode() const
418 sal_uInt32 lError
= pImp
->m_eError
;
419 if(!lError
&& pImp
->m_pInStream
)
420 lError
= pImp
->m_pInStream
->GetErrorCode();
421 if(!lError
&& pImp
->m_pOutStream
)
422 lError
= pImp
->m_pOutStream
->GetErrorCode();
426 //------------------------------------------------------------------
427 void SfxMedium::CheckFileDate( const util::DateTime
& aInitDate
)
429 GetInitFileDate( true );
430 if ( pImp
->m_aDateTime
.Seconds
!= aInitDate
.Seconds
431 || pImp
->m_aDateTime
.Minutes
!= aInitDate
.Minutes
432 || pImp
->m_aDateTime
.Hours
!= aInitDate
.Hours
433 || pImp
->m_aDateTime
.Day
!= aInitDate
.Day
434 || pImp
->m_aDateTime
.Month
!= aInitDate
.Month
435 || pImp
->m_aDateTime
.Year
!= aInitDate
.Year
)
437 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
443 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
444 document::ChangedByOthersRequest() ) );
445 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 3 );
446 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl
.get() );
447 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl
.get() );
448 xInteractionRequestImpl
->setContinuations( aContinuations
);
450 xHandler
->handle( xInteractionRequestImpl
.get() );
452 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xInteractionRequestImpl
->getSelection();
453 if ( uno::Reference
< task::XInteractionAbort
>( xSelected
.get(), uno::UNO_QUERY
).is() )
455 SetError( ERRCODE_ABORT
, OUString( OSL_LOG_PREFIX
) );
458 catch ( const uno::Exception
& )
464 //------------------------------------------------------------------
465 sal_Bool
SfxMedium::DocNeedsFileDateCheck()
467 return ( !IsReadOnly() && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) );
470 //------------------------------------------------------------------
471 util::DateTime
SfxMedium::GetInitFileDate( sal_Bool bIgnoreOldValue
)
473 if ( ( bIgnoreOldValue
|| !pImp
->m_bGotDateTime
) && !pImp
->m_aLogicName
.isEmpty() )
477 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
478 ::ucbhelper::Content
aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, comphelper::getProcessComponentContext() );
480 aContent
.getPropertyValue( OUString("DateModified" ) ) >>= pImp
->m_aDateTime
;
481 pImp
->m_bGotDateTime
= true;
483 catch ( const ::com::sun::star::uno::Exception
& )
488 return pImp
->m_aDateTime
;
491 //------------------------------------------------------------------
492 Reference
< XContent
> SfxMedium::GetContent() const
494 if ( !pImp
->aContent
.get().is() )
496 Reference
< ::com::sun::star::ucb::XContent
> xContent
;
497 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
499 SFX_ITEMSET_ARG( pImp
->m_pSet
, pItem
, SfxUnoAnyItem
, SID_CONTENT
, false);
501 pItem
->GetValue() >>= xContent
;
507 pImp
->aContent
= ::ucbhelper::Content( xContent
, xEnv
, comphelper::getProcessComponentContext() );
509 catch ( const Exception
& )
515 // TODO: OSL_FAIL("SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
517 if ( !pImp
->m_aName
.isEmpty() )
518 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aURL
);
519 else if ( !pImp
->m_aLogicName
.isEmpty() )
520 aURL
= GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
521 if (!aURL
.isEmpty() )
522 ::ucbhelper::Content::create( aURL
, xEnv
, comphelper::getProcessComponentContext(), pImp
->aContent
);
526 return pImp
->aContent
.get();
529 //------------------------------------------------------------------
530 OUString
SfxMedium::GetBaseURL( bool bForSaving
)
533 const SfxStringItem
* pBaseURLItem
= static_cast<const SfxStringItem
*>( GetItemSet()->GetItem(SID_DOC_BASEURL
) );
535 aBaseURL
= pBaseURLItem
->GetValue();
536 else if ( GetContent().is() )
540 Any aAny
= pImp
->aContent
.getPropertyValue( OUString("BaseURI" ) );
543 catch ( const ::com::sun::star::uno::Exception
& )
547 if ( aBaseURL
.isEmpty() )
548 aBaseURL
= GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
554 bool bIsRemote
= IsRemote();
555 if( (bIsRemote
&& !aOpt
.IsSaveRelINet()) || (!pImp
->m_bRemote
&& !aOpt
.IsSaveRelFSys()) )
562 //------------------------------------------------------------------
563 SvStream
* SfxMedium::GetInStream()
565 if ( pImp
->m_pInStream
)
566 return pImp
->m_pInStream
;
568 if ( pImp
->pTempFile
)
570 pImp
->m_pInStream
= new SvFileStream(pImp
->m_aName
, pImp
->m_nStorOpenMode
);
572 pImp
->m_eError
= pImp
->m_pInStream
->GetError();
574 if (!pImp
->m_eError
&& (pImp
->m_nStorOpenMode
& STREAM_WRITE
)
575 && ! pImp
->m_pInStream
->IsWritable() )
577 pImp
->m_eError
= ERRCODE_IO_ACCESSDENIED
;
578 delete pImp
->m_pInStream
;
579 pImp
->m_pInStream
= NULL
;
582 return pImp
->m_pInStream
;
590 return pImp
->m_pInStream
;
593 //------------------------------------------------------------------
594 void SfxMedium::CloseInStream()
596 CloseInStream_Impl();
599 void SfxMedium::CloseInStream_Impl()
601 // if there is a storage based on the InStream, we have to
602 // close the storage, too, because otherwise the storage
603 // would use an invalid ( deleted ) stream.
604 if ( pImp
->m_pInStream
&& pImp
->xStorage
.is() )
606 if ( pImp
->bStorageBasedOnInStream
)
610 if ( pImp
->m_pInStream
&& !GetContent().is() )
612 CreateTempFile( true );
616 DELETEZ( pImp
->m_pInStream
);
618 pImp
->m_pSet
->ClearItem( SID_INPUTSTREAM
);
620 CloseZipStorage_Impl();
621 pImp
->xInputStream
.clear();
623 if ( !pImp
->m_pOutStream
)
625 // output part of the stream is not used so the whole stream can be closed
626 // TODO/LATER: is it correct?
627 pImp
->xStream
.clear();
629 pImp
->m_pSet
->ClearItem( SID_STREAM
);
633 //------------------------------------------------------------------
634 SvStream
* SfxMedium::GetOutStream()
636 if ( !pImp
->m_pOutStream
)
638 // Create a temp. file if there is none because we always
640 CreateTempFile( false );
642 if ( pImp
->pTempFile
)
644 // On windows we try to re-use XOutStream from xStream if that exists;
645 // because opening new SvFileStream in this situation may fail with ERROR_SHARING_VIOLATION
647 if (pImp
->xStream
.is())
649 assert(pImp
->xStream
->getOutputStream().is()); // need that...
650 pImp
->m_pOutStream
= utl::UcbStreamHelper::CreateStream(
651 pImp
->xStream
, false);
655 pImp
->m_pOutStream
= new SvFileStream(
656 pImp
->m_aName
, STREAM_STD_READWRITE
);
658 // On Unix don't try to re-use XOutStream from xStream if that exists;
659 // it causes fdo#59022 (fails opening files via SMB on Linux)
661 pImp
->m_pOutStream
= new SvFileStream(
662 pImp
->m_aName
, STREAM_STD_READWRITE
);
668 return pImp
->m_pOutStream
;
671 //------------------------------------------------------------------
672 sal_Bool
SfxMedium::CloseOutStream()
674 CloseOutStream_Impl();
678 sal_Bool
SfxMedium::CloseOutStream_Impl()
680 if ( pImp
->m_pOutStream
)
682 // if there is a storage based on the OutStream, we have to
683 // close the storage, too, because otherwise the storage
684 // would use an invalid ( deleted ) stream.
685 //TODO/MBA: how to deal with this?!
686 //maybe we need a new flag when the storage was created from the outstream
687 if ( pImp
->xStorage
.is() )
692 delete pImp
->m_pOutStream
;
693 pImp
->m_pOutStream
= NULL
;
696 if ( !pImp
->m_pInStream
)
698 // input part of the stream is not used so the whole stream can be closed
699 // TODO/LATER: is it correct?
700 pImp
->xStream
.clear();
702 pImp
->m_pSet
->ClearItem( SID_STREAM
);
708 //------------------------------------------------------------------
709 const OUString
& SfxMedium::GetPhysicalName() const
711 if ( pImp
->m_aName
.isEmpty() && !pImp
->m_aLogicName
.isEmpty() )
712 (( SfxMedium
*)this)->CreateFileStream();
714 // return the name then
715 return pImp
->m_aName
;
718 //------------------------------------------------------------------
719 void SfxMedium::CreateFileStream()
721 ForceSynchronStream_Impl( true );
723 if( pImp
->m_pInStream
)
725 CreateTempFile( false );
726 pImp
->bIsTemp
= true;
727 CloseInStream_Impl();
731 //------------------------------------------------------------------
732 sal_Bool
SfxMedium::Commit()
734 if( pImp
->xStorage
.is() )
735 StorageCommit_Impl();
736 else if( pImp
->m_pOutStream
)
737 pImp
->m_pOutStream
->Flush();
738 else if( pImp
->m_pInStream
)
739 pImp
->m_pInStream
->Flush();
741 if ( GetError() == SVSTREAM_OK
)
743 // does something only in case there is a temporary file ( means aName points to different location than aLogicName )
747 bool bResult
= ( GetError() == SVSTREAM_OK
);
749 if ( bResult
&& DocNeedsFileDateCheck() )
750 GetInitFileDate( true );
752 // remove truncation mode from the flags
753 pImp
->m_nStorOpenMode
&= (~STREAM_TRUNC
);
757 //------------------------------------------------------------------
758 sal_Bool
SfxMedium::IsStorage()
760 if ( pImp
->xStorage
.is() )
763 if ( pImp
->m_bTriedStorage
)
764 return pImp
->bIsStorage
;
766 if ( pImp
->pTempFile
)
769 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aURL
) )
771 OSL_FAIL("Physical name not convertible!");
773 pImp
->bIsStorage
= SotStorage::IsStorageFile( aURL
) && !SotStorage::IsOLEStorage( aURL
);
774 if ( !pImp
->bIsStorage
)
775 pImp
->m_bTriedStorage
= true;
777 else if ( GetInStream() )
779 pImp
->bIsStorage
= SotStorage::IsStorageFile( pImp
->m_pInStream
) && !SotStorage::IsOLEStorage( pImp
->m_pInStream
);
780 if ( !pImp
->m_pInStream
->GetError() && !pImp
->bIsStorage
)
781 pImp
->m_bTriedStorage
= true;
784 return pImp
->bIsStorage
;
787 //------------------------------------------------------------------
788 sal_Bool
SfxMedium::IsPreview_Impl()
790 bool bPreview
= false;
791 SFX_ITEMSET_ARG( GetItemSet(), pPreview
, SfxBoolItem
, SID_PREVIEW
, false);
793 bPreview
= pPreview
->GetValue();
796 SFX_ITEMSET_ARG( GetItemSet(), pFlags
, SfxStringItem
, SID_OPTIONS
, false);
799 String aFileFlags
= pFlags
->GetValue();
800 aFileFlags
.ToUpperAscii();
801 if ( STRING_NOTFOUND
!= aFileFlags
.Search( 'B' ) )
809 //------------------------------------------------------------------
810 void SfxMedium::StorageBackup_Impl()
812 ::ucbhelper::Content aOriginalContent
;
813 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
815 bool bBasedOnOriginalFile
= ( !pImp
->pTempFile
&& !( !pImp
->m_aLogicName
.isEmpty() && pImp
->m_bSalvageMode
)
816 && !GetURLObject().GetMainURL( INetURLObject::NO_DECODE
).isEmpty()
817 && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
818 && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) );
820 if ( bBasedOnOriginalFile
&& pImp
->m_aBackupURL
.isEmpty()
821 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, comphelper::getProcessComponentContext(), aOriginalContent
) )
823 DoInternalBackup_Impl( aOriginalContent
);
824 if( pImp
->m_aBackupURL
.isEmpty() )
825 SetError( ERRCODE_SFX_CANTCREATEBACKUP
, OUString( OSL_LOG_PREFIX
) );
829 //------------------------------------------------------------------
830 OUString
SfxMedium::GetBackup_Impl()
832 if ( pImp
->m_aBackupURL
.isEmpty() )
833 StorageBackup_Impl();
835 return pImp
->m_aBackupURL
;
838 //------------------------------------------------------------------
839 uno::Reference
< embed::XStorage
> SfxMedium::GetOutputStorage()
842 return uno::Reference
< embed::XStorage
>();
844 // if the medium was constructed with a Storage: use this one, not a temp. storage
845 // if a temporary storage already exists: use it
846 if ( pImp
->xStorage
.is() && ( pImp
->m_aLogicName
.isEmpty() || pImp
->pTempFile
) )
847 return pImp
->xStorage
;
849 // if necessary close stream that was used for reading
850 if ( pImp
->m_pInStream
&& !pImp
->m_pInStream
->IsWritable() )
853 DBG_ASSERT( !pImp
->m_pOutStream
, "OutStream in a readonly Medium?!" );
855 // TODO/LATER: The current solution is to store the document temporary and then copy it to the target location;
856 // in future it should be stored directly and then copied to the temporary location, since in this case no
857 // file attributes have to be preserved and system copying mechanics could be used instead of streaming.
858 CreateTempFileNoCopy();
863 //------------------------------------------------------------------
864 void SfxMedium::SetEncryptionDataToStorage_Impl()
866 // in case media-descriptor contains password it should be used on opening
867 if ( pImp
->xStorage
.is() && pImp
->m_pSet
)
869 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
870 if ( GetEncryptionData_Impl( pImp
->m_pSet
, aEncryptionData
) )
872 // replace the password with encryption data
873 pImp
->m_pSet
->ClearItem( SID_PASSWORD
);
874 pImp
->m_pSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
878 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( pImp
->xStorage
, aEncryptionData
);
880 catch( const uno::Exception
& )
882 OSL_FAIL( "It must be possible to set a common password for the storage" );
883 // TODO/LATER: set the error code in case of problem
884 // SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
890 //------------------------------------------------------------------
891 sal_Int8
SfxMedium::ShowLockedDocumentDialog( const uno::Sequence
< OUString
>& aData
, sal_Bool bIsLoading
, sal_Bool bOwnLock
)
893 sal_Int8 nResult
= LOCK_UI_NOLOCK
;
895 // show the interaction regarding the document opening
896 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
898 if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler
.is() && ( bIsLoading
|| bOwnLock
) )
900 OUString aDocumentURL
= GetURLObject().GetLastName();
902 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xInteractionRequestImpl
;
906 if ( aData
.getLength() > LOCKFILE_EDITTIME_ID
)
907 aInfo
= aData
[LOCKFILE_EDITTIME_ID
];
909 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
910 document::OwnLockOnDocumentRequest( OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
, !bIsLoading
) ) );
914 if ( aData
.getLength() > LOCKFILE_EDITTIME_ID
)
916 if ( !aData
[LOCKFILE_OOOUSERNAME_ID
].isEmpty() )
917 aInfo
= aData
[LOCKFILE_OOOUSERNAME_ID
];
919 aInfo
= aData
[LOCKFILE_SYSUSERNAME_ID
];
921 if ( !aInfo
.isEmpty() && !aData
[LOCKFILE_EDITTIME_ID
].isEmpty() )
923 aInfo
+= OUString( " ( " );
924 aInfo
+= aData
[LOCKFILE_EDITTIME_ID
];
925 aInfo
+= OUString( " )" );
931 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
932 document::LockedDocumentRequest( OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
) ) );
936 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
937 document::LockedOnSavingRequest( OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
) ) );
942 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 3 );
943 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl
.get() );
944 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl
.get() );
945 aContinuations
[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl
.get() );
946 xInteractionRequestImpl
->setContinuations( aContinuations
);
948 xHandler
->handle( xInteractionRequestImpl
.get() );
950 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xInteractionRequestImpl
->getSelection();
951 if ( uno::Reference
< task::XInteractionAbort
>( xSelected
.get(), uno::UNO_QUERY
).is() )
953 SetError( ERRCODE_ABORT
, OUString( OSL_LOG_PREFIX
) );
955 else if ( uno::Reference
< task::XInteractionDisapprove
>( xSelected
.get(), uno::UNO_QUERY
).is() )
957 // own lock on loading, user has selected to ignore the lock
958 // own lock on saving, user has selected to ignore the lock
959 // alien lock on loading, user has selected to edit a copy of document
960 // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
961 if ( bIsLoading
&& !bOwnLock
)
963 // means that a copy of the document should be opened
964 GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE
, true ) );
967 nResult
= LOCK_UI_SUCCEEDED
;
969 else // if ( XSelected == aContinuations[1] )
971 // own lock on loading, user has selected to open readonly
972 // own lock on saving, user has selected to open readonly
973 // alien lock on loading, user has selected to retry saving
974 // TODO/LATER: alien lock on saving, user has selected to retry saving
977 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
979 nResult
= LOCK_UI_TRY
;
986 // if no interaction handler is provided the default answer is open readonly
987 // that usually happens in case the document is loaded per API
988 // so the document must be opened readonly for backward compatibility
989 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
992 SetError( ERRCODE_IO_ACCESSDENIED
, OUString( OSL_LOG_PREFIX
) );
1001 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
1002 bool isSuitableProtocolForLocking(const String
& rLogicName
)
1004 INetURLObject
aUrl( rLogicName
);
1005 INetProtocol eProt
= aUrl
.GetProtocol();
1006 return eProt
== INET_PROT_FILE
|| eProt
== INET_PROT_SFTP
;
1011 // returns true if the document can be opened for editing ( even if it should be a copy )
1012 // otherwise the document should be opened readonly
1013 // if user cancel the loading the ERROR_ABORT is set
1014 bool SfxMedium::LockOrigFileOnDemand( sal_Bool bLoading
, sal_Bool bNoUI
)
1016 #if !HAVE_FEATURE_MULTIUSER_ENVIRONMENT
1021 if (!IsLockingUsed())
1024 if ( GetURLObject().HasError() )
1027 bool bResult
= false;
1030 if ( pImp
->m_bLocked
&& bLoading
&& ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
1032 // if the document is already locked the system locking might be temporarely off after storing
1033 // check whether the system file locking should be taken again
1034 GetLockingStream_Impl();
1037 bResult
= pImp
->m_bLocked
;
1041 // no read-write access is necessary on loading if the document is explicitly opened as copy
1042 SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem
, SfxBoolItem
, SID_TEMPLATE
, false);
1043 bResult
= ( bLoading
&& pTemplateItem
&& pTemplateItem
->GetValue() );
1046 if ( !bResult
&& !IsReadOnly() )
1048 bool bContentReadonly
= false;
1049 if ( bLoading
&& ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
1051 // let the original document be opened to check the possibility to open it for editing
1052 // and to let the writable stream stay open to hold the lock on the document
1053 GetLockingStream_Impl();
1056 // "IsReadOnly" property does not allow to detect whether the file is readonly always
1057 // so we try always to open the file for editing
1058 // the file is readonly only in case the read-write stream can not be opened
1059 if ( bLoading
&& !pImp
->m_xLockingStream
.is() )
1063 // MediaDescriptor does this check also, the duplication should be avoided in future
1064 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1065 ::ucbhelper::Content
aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, comphelper::getProcessComponentContext() );
1066 aContent
.getPropertyValue( OUString( "IsReadOnly" ) ) >>= bContentReadonly
;
1068 catch( const uno::Exception
& ) {}
1071 // This block was introduced as a fix to i#102464, but removing
1072 // this does not make the problem re-appear. But leaving this
1073 // part would interfere with documents saved in samba share. This
1074 // affects Windows only.
1075 if ( !bContentReadonly
)
1077 // the file is not readonly, check the ACL
1080 if ( ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), aPhysPath
) )
1081 bContentReadonly
= IsReadonlyAccordingACL( aPhysPath
.GetBuffer() );
1085 if ( bContentReadonly
)
1086 pImp
->m_bOriginallyReadOnly
= true;
1089 // do further checks only if the file not readonly in fs
1090 if ( !bContentReadonly
)
1092 // the special file locking should be used only for suitable URLs
1093 if ( isSuitableProtocolForLocking( pImp
->m_aLogicName
) )
1096 // in case of storing the document should request the output before locking
1099 // let the stream be opened to check the system file locking
1103 sal_Int8 bUIStatus
= LOCK_UI_NOLOCK
;
1105 // check whether system file locking has been used, the default value is false
1106 bool bUseSystemLock
= ::utl::LocalFileHelper::IsLocalFile( pImp
->m_aLogicName
) && IsSystemFileLockingUsed();
1108 // TODO/LATER: This implementation does not allow to detect the system lock on saving here, actually this is no big problem
1109 // if system lock is used the writeable stream should be available
1110 bool bHandleSysLocked
= ( bLoading
&& bUseSystemLock
&& !pImp
->xStream
.is() && !pImp
->m_pOutStream
);
1116 ::svt::DocumentLockFile
aLockFile( pImp
->m_aLogicName
);
1117 if ( !bHandleSysLocked
)
1121 bResult
= aLockFile
.CreateOwnLockFile();
1123 catch ( const ucb::InteractiveIOException
& e
)
1125 // exception means that the lock file can not be successfully accessed
1126 // in this case it should be ignored if system file locking is anyway active
1127 if ( bUseSystemLock
|| !IsOOoLockFileUsed() )
1130 // take the ownership over the lock file
1131 aLockFile
.OverwriteOwnLockFile();
1133 else if ( e
.Code
== IOErrorCode_INVALID_PARAMETER
)
1135 // system file locking is not active, ask user whether he wants to open the document without any locking
1136 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
1138 if ( xHandler
.is() )
1140 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xIgnoreRequestImpl
1141 = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
1143 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 2 );
1144 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl
.get() );
1145 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl
.get() );
1146 xIgnoreRequestImpl
->setContinuations( aContinuations
);
1148 xHandler
->handle( xIgnoreRequestImpl
.get() );
1150 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xIgnoreRequestImpl
->getSelection();
1151 bResult
= uno::Reference
< task::XInteractionApprove
>( xSelected
.get(), uno::UNO_QUERY
).is();
1155 catch ( const uno::Exception
& )
1157 // exception means that the lock file can not be successfully accessed
1158 // in this case it should be ignored if system file locking is anyway active
1159 if ( bUseSystemLock
|| !IsOOoLockFileUsed() )
1162 // take the ownership over the lock file
1163 aLockFile
.OverwriteOwnLockFile();
1167 // in case OOo locking is turned off the lock file is still written if possible
1168 // but it is ignored while deciding whether the document should be opened for editing or not
1169 if ( !bResult
&& !IsOOoLockFileUsed() )
1172 // take the ownership over the lock file
1173 aLockFile
.OverwriteOwnLockFile();
1180 uno::Sequence
< OUString
> aData
;
1183 // impossibility to get data is no real problem
1184 aData
= aLockFile
.GetLockData();
1186 catch( const uno::Exception
& )
1190 bool bOwnLock
= false;
1192 if ( !bHandleSysLocked
)
1194 uno::Sequence
< OUString
> aOwnData
= aLockFile
.GenerateOwnEntry();
1195 bOwnLock
= ( aData
.getLength() > LOCKFILE_USERURL_ID
1196 && aOwnData
.getLength() > LOCKFILE_USERURL_ID
1197 && aOwnData
[LOCKFILE_SYSUSERNAME_ID
].equals( aData
[LOCKFILE_SYSUSERNAME_ID
] ) );
1200 && aOwnData
[LOCKFILE_LOCALHOST_ID
].equals( aData
[LOCKFILE_LOCALHOST_ID
] )
1201 && aOwnData
[LOCKFILE_USERURL_ID
].equals( aData
[LOCKFILE_USERURL_ID
] ) )
1203 // this is own lock from the same installation, it could remain because of crash
1208 if ( !bResult
&& !bNoUI
)
1210 bUIStatus
= ShowLockedDocumentDialog( aData
, bLoading
, bOwnLock
);
1211 if ( bUIStatus
== LOCK_UI_SUCCEEDED
)
1213 // take the ownership over the lock file
1214 bResult
= aLockFile
.OverwriteOwnLockFile();
1218 bHandleSysLocked
= false;
1221 catch( const uno::Exception
& )
1224 } while( !bResult
&& bUIStatus
== LOCK_UI_TRY
);
1226 pImp
->m_bLocked
= bResult
;
1230 // this is no file URL, check whether the file is readonly
1231 bResult
= !bContentReadonly
;
1236 if ( !bResult
&& GetError() == ERRCODE_NONE
)
1238 // the error should be set in case it is storing process
1239 // or the document has been opened for editing explicitly
1240 SFX_ITEMSET_ARG( pImp
->m_pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, false );
1242 if ( !bLoading
|| (pReadOnlyItem
&& !pReadOnlyItem
->GetValue()) )
1243 SetError( ERRCODE_IO_ACCESSDENIED
, OUString( OSL_LOG_PREFIX
) );
1245 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
1248 // when the file is locked, get the current file date
1249 if ( bResult
&& DocNeedsFileDateCheck() )
1250 GetInitFileDate( true );
1252 catch( const uno::Exception
& )
1254 OSL_FAIL( "Locking exception: high probability, that the content has not been created" );
1260 //------------------------------------------------------------------
1261 uno::Reference
< embed::XStorage
> SfxMedium::GetStorage( sal_Bool bCreateTempIfNo
)
1263 if ( pImp
->xStorage
.is() || pImp
->m_bTriedStorage
)
1264 return pImp
->xStorage
;
1266 uno::Sequence
< uno::Any
> aArgs( 2 );
1268 // the medium should be retrieved before temporary file creation
1269 // to let the MediaDescriptor be filled with the streams
1272 if ( bCreateTempIfNo
)
1273 CreateTempFile( false );
1278 return pImp
->xStorage
;
1280 SFX_ITEMSET_ARG( GetItemSet(), pRepairItem
, SfxBoolItem
, SID_REPAIRPACKAGE
, false);
1281 if ( pRepairItem
&& pRepairItem
->GetValue() )
1283 // the storage should be created for repairing mode
1284 CreateTempFile( false );
1287 Reference
< ::com::sun::star::ucb::XProgressHandler
> xProgressHandler
;
1288 Reference
< ::com::sun::star::task::XStatusIndicator
> xStatusIndicator
;
1290 SFX_ITEMSET_ARG( GetItemSet(), pxProgressItem
, SfxUnoAnyItem
, SID_PROGRESS_STATUSBAR_CONTROL
, false );
1291 if( pxProgressItem
&& ( pxProgressItem
->GetValue() >>= xStatusIndicator
) )
1292 xProgressHandler
= Reference
< ::com::sun::star::ucb::XProgressHandler
>(
1293 new utl::ProgressHandlerWrap( xStatusIndicator
) );
1295 uno::Sequence
< beans::PropertyValue
> aAddProps( 2 );
1296 aAddProps
[0].Name
= OUString("RepairPackage");
1297 aAddProps
[0].Value
<<= (sal_Bool
)true;
1298 aAddProps
[1].Name
= OUString("StatusIndicator");
1299 aAddProps
[1].Value
<<= xProgressHandler
;
1301 // the first arguments will be filled later
1303 aArgs
[2] <<= aAddProps
;
1306 if ( pImp
->xStream
.is() )
1308 // since the storage is based on temporary stream we open it always read-write
1309 aArgs
[0] <<= pImp
->xStream
;
1310 aArgs
[1] <<= embed::ElementModes::READWRITE
;
1311 pImp
->bStorageBasedOnInStream
= true;
1313 else if ( pImp
->xInputStream
.is() )
1315 // since the storage is based on temporary stream we open it always read-write
1316 aArgs
[0] <<= pImp
->xInputStream
;
1317 aArgs
[1] <<= embed::ElementModes::READ
;
1318 pImp
->bStorageBasedOnInStream
= true;
1322 CloseStreams_Impl();
1323 aArgs
[0] <<= pImp
->m_aName
;
1324 aArgs
[1] <<= embed::ElementModes::READ
;
1325 pImp
->bStorageBasedOnInStream
= false;
1330 pImp
->xStorage
= uno::Reference
< embed::XStorage
>(
1331 ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs
),
1334 catch( const uno::Exception
& )
1336 // impossibility to create the storage is no error
1339 if( ( pImp
->nLastStorageError
= GetError() ) != SVSTREAM_OK
)
1342 if ( pImp
->m_pInStream
)
1343 pImp
->m_pInStream
->Seek(0);
1344 return uno::Reference
< embed::XStorage
>();
1347 pImp
->m_bTriedStorage
= true;
1349 // TODO/LATER: Get versionlist on demand
1350 if ( pImp
->xStorage
.is() )
1352 SetEncryptionDataToStorage_Impl();
1356 SFX_ITEMSET_ARG( pImp
->m_pSet
, pVersion
, SfxInt16Item
, SID_VERSION
, false);
1358 bool bResetStorage
= false;
1359 if ( pVersion
&& pVersion
->GetValue() )
1361 // Read all available versions
1362 if ( pImp
->aVersions
.getLength() )
1364 // Search for the version fits the comment
1365 // The versions are numbered startign with 1, versions with
1366 // negative versions numbers are counted backwards from the
1368 short nVersion
= pVersion
? pVersion
->GetValue() : 0;
1370 nVersion
= ( (short) pImp
->aVersions
.getLength() ) + nVersion
;
1371 else if ( nVersion
)
1374 util::RevisionTag
& rTag
= pImp
->aVersions
[nVersion
];
1376 // Open SubStorage for all versions
1377 uno::Reference
< embed::XStorage
> xSub
= pImp
->xStorage
->openStorageElement( "Versions",
1378 embed::ElementModes::READ
);
1380 DBG_ASSERT( xSub
.is(), "Version list, but no Versions!" );
1382 // There the version is stored as packed Stream
1383 uno::Reference
< io::XStream
> xStr
= xSub
->openStreamElement( rTag
.Identifier
, embed::ElementModes::READ
);
1384 SvStream
* pStream
= utl::UcbStreamHelper::CreateStream( xStr
);
1385 if ( pStream
&& pStream
->GetError() == SVSTREAM_OK
)
1387 // Unpack Stream in TempDir
1388 ::utl::TempFile aTempFile
;
1389 String aTmpName
= aTempFile
.GetURL();
1390 SvFileStream
aTmpStream( aTmpName
, SFX_STREAM_READWRITE
);
1392 *pStream
>> aTmpStream
;
1395 // Open data as Storage
1396 pImp
->m_nStorOpenMode
= SFX_STREAM_READONLY
;
1397 pImp
->xStorage
= comphelper::OStorageHelper::GetStorageFromURL( aTmpName
, embed::ElementModes::READ
);
1398 pImp
->bStorageBasedOnInStream
= false;
1400 ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName
, aTemp
);
1401 SetPhysicalName_Impl( aTemp
);
1403 pImp
->bIsTemp
= true;
1404 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
1406 pImp
->aVersions
.realloc(0);
1409 bResetStorage
= true;
1413 bResetStorage
= true;
1416 if ( bResetStorage
)
1418 pImp
->xStorage
.clear();
1419 if ( pImp
->m_pInStream
)
1420 pImp
->m_pInStream
->Seek( 0L );
1423 pImp
->bIsStorage
= pImp
->xStorage
.is();
1424 return pImp
->xStorage
;
1427 //------------------------------------------------------------------
1428 uno::Reference
< embed::XStorage
> SfxMedium::GetZipStorageToSign_Impl( sal_Bool bReadOnly
)
1430 if ( !GetError() && !pImp
->m_xZipStorage
.is() )
1436 // we can not sign document if there is no stream
1437 // should it be possible at all?
1438 if ( !bReadOnly
&& pImp
->xStream
.is() )
1440 pImp
->m_xZipStorage
= ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xStream
, embed::ElementModes::READWRITE
);
1442 else if ( pImp
->xInputStream
.is() )
1444 pImp
->m_xZipStorage
= ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xInputStream
);
1447 catch( const uno::Exception
& )
1449 OSL_FAIL( "No possibility to get readonly version of storage from medium!\n" );
1452 if ( GetError() ) // do not remove warnings
1456 return pImp
->m_xZipStorage
;
1459 //------------------------------------------------------------------
1460 void SfxMedium::CloseZipStorage_Impl()
1462 if ( pImp
->m_xZipStorage
.is() )
1465 pImp
->m_xZipStorage
->dispose();
1466 } catch( const uno::Exception
& )
1469 pImp
->m_xZipStorage
.clear();
1473 void SfxMedium::CloseStorage()
1475 if ( pImp
->xStorage
.is() )
1477 uno::Reference
< lang::XComponent
> xComp( pImp
->xStorage
, uno::UNO_QUERY
);
1478 // in the salvage mode the medium does not own the storage
1479 if ( pImp
->bDisposeStorage
&& !pImp
->m_bSalvageMode
)
1483 } catch( const uno::Exception
& )
1485 OSL_FAIL( "Medium's storage is already disposed!\n" );
1489 pImp
->xStorage
.clear();
1490 pImp
->bStorageBasedOnInStream
= false;
1493 pImp
->m_bTriedStorage
= false;
1494 pImp
->bIsStorage
= false;
1497 void SfxMedium::CanDisposeStorage_Impl( sal_Bool bDisposeStorage
)
1499 pImp
->bDisposeStorage
= bDisposeStorage
;
1502 sal_Bool
SfxMedium::WillDisposeStorageOnClose_Impl()
1504 return pImp
->bDisposeStorage
;
1507 StreamMode
SfxMedium::GetOpenMode() const
1509 return pImp
->m_nStorOpenMode
;
1512 void SfxMedium::SetOpenMode( StreamMode nStorOpen
,
1513 sal_Bool bDontClose
)
1515 if ( pImp
->m_nStorOpenMode
!= nStorOpen
)
1517 pImp
->m_nStorOpenMode
= nStorOpen
;
1521 if ( pImp
->xStorage
.is() )
1524 CloseStreams_Impl();
1529 //------------------------------------------------------------------
1530 sal_Bool
SfxMedium::UseBackupToRestore_Impl( ::ucbhelper::Content
& aOriginalContent
,
1531 const Reference
< ::com::sun::star::ucb::XCommandEnvironment
>& xComEnv
)
1535 ::ucbhelper::Content
aTransactCont( pImp
->m_aBackupURL
, xComEnv
, comphelper::getProcessComponentContext() );
1537 Reference
< XInputStream
> aOrigInput
= aTransactCont
.openStream();
1538 aOriginalContent
.writeStream( aOrigInput
, true );
1541 catch( const Exception
& )
1543 // in case of failure here the backup file should not be removed
1544 // TODO/LATER: a message should be used to let user know about the backup
1545 pImp
->m_bRemoveBackup
= false;
1546 // TODO/LATER: needs a specific error code
1547 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1553 //------------------------------------------------------------------
1554 sal_Bool
SfxMedium::StorageCommit_Impl()
1556 bool bResult
= false;
1557 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1558 ::ucbhelper::Content aOriginalContent
;
1560 if ( pImp
->xStorage
.is() )
1564 uno::Reference
< embed::XTransactedObject
> xTrans( pImp
->xStorage
, uno::UNO_QUERY
);
1570 CloseZipStorage_Impl();
1573 catch ( const embed::UseBackupException
& aBackupExc
)
1575 // since the temporary file is created always now, the scenario is close to be impossible
1576 if ( !pImp
->pTempFile
)
1578 OSL_ENSURE( !pImp
->m_aBackupURL
.isEmpty(), "No backup on storage commit!\n" );
1579 if ( !pImp
->m_aBackupURL
.isEmpty()
1580 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
),
1581 xDummyEnv
, comphelper::getProcessComponentContext(),
1582 aOriginalContent
) )
1584 // use backup to restore the file
1585 // the storage has already disconnected from original location
1586 CloseAndReleaseStreams_Impl();
1587 if ( !UseBackupToRestore_Impl( aOriginalContent
, xDummyEnv
) )
1589 // connect the medium to the temporary file of the storage
1590 pImp
->aContent
= ::ucbhelper::Content();
1591 pImp
->m_aName
= aBackupExc
.TemporaryFileURL
;
1592 OSL_ENSURE( !pImp
->m_aName
.isEmpty(), "The exception _must_ contain the temporary URL!\n" );
1597 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1600 catch ( const uno::Exception
& )
1602 //TODO/LATER: improve error handling
1603 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1612 //------------------------------------------------------------------
1613 sal_Bool
SfxMedium::TransactedTransferForFS_Impl( const INetURLObject
& aSource
,
1614 const INetURLObject
& aDest
,
1615 const Reference
< ::com::sun::star::ucb::XCommandEnvironment
>& xComEnv
)
1617 bool bResult
= false;
1618 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1619 Reference
< XOutputStream
> aDestStream
;
1620 ::ucbhelper::Content aOriginalContent
;
1624 aOriginalContent
= ::ucbhelper::Content( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
, comphelper::getProcessComponentContext() );
1626 catch ( const ::com::sun::star::ucb::CommandAbortedException
& )
1628 pImp
->m_eError
= ERRCODE_ABORT
;
1630 catch ( const ::com::sun::star::ucb::CommandFailedException
& )
1632 pImp
->m_eError
= ERRCODE_ABORT
;
1634 catch (const ::com::sun::star::ucb::ContentCreationException
& ex
)
1636 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1638 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER
) ||
1639 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED
)
1642 pImp
->m_eError
= ERRCODE_IO_NOTEXISTSPATH
;
1645 catch (const ::com::sun::star::uno::Exception
&)
1647 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1650 if( !pImp
->m_eError
|| (pImp
->m_eError
& ERRCODE_WARNING_MASK
) )
1652 if ( pImp
->xStorage
.is() )
1655 CloseStreams_Impl();
1657 ::ucbhelper::Content aTempCont
;
1658 if( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, comphelper::getProcessComponentContext(), aTempCont
) )
1660 bool bTransactStarted
= false;
1661 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, false );
1662 SFX_ITEMSET_ARG( GetItemSet(), pRename
, SfxBoolItem
, SID_RENAME
, false );
1663 bool bRename
= pRename
? pRename
->GetValue() : false;
1664 bool bOverWrite
= pOverWrite
? pOverWrite
->GetValue() : !bRename
;
1668 if( bOverWrite
&& ::utl::UCBContentHelper::IsDocument( aDest
.GetMainURL( INetURLObject::NO_DECODE
) ) )
1670 if( pImp
->m_aBackupURL
.isEmpty() )
1671 DoInternalBackup_Impl( aOriginalContent
);
1673 if( !pImp
->m_aBackupURL
.isEmpty() )
1675 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1676 bTransactStarted
= true;
1677 aOriginalContent
.setPropertyValue( "Size", uno::makeAny( (sal_Int64
)0 ) );
1678 aOriginalContent
.writeStream( aTempInput
, bOverWrite
);
1683 pImp
->m_eError
= ERRCODE_SFX_CANTCREATEBACKUP
;
1688 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1689 aOriginalContent
.writeStream( aTempInput
, bOverWrite
);
1693 catch ( const ::com::sun::star::ucb::CommandAbortedException
& )
1695 pImp
->m_eError
= ERRCODE_ABORT
;
1697 catch ( const ::com::sun::star::ucb::CommandFailedException
& )
1699 pImp
->m_eError
= ERRCODE_ABORT
;
1701 catch ( const ::com::sun::star::ucb::InteractiveIOException
& r
)
1703 if ( r
.Code
== IOErrorCode_ACCESS_DENIED
)
1704 pImp
->m_eError
= ERRCODE_IO_ACCESSDENIED
;
1705 else if ( r
.Code
== IOErrorCode_NOT_EXISTING
)
1706 pImp
->m_eError
= ERRCODE_IO_NOTEXISTS
;
1707 else if ( r
.Code
== IOErrorCode_CANT_READ
)
1708 pImp
->m_eError
= ERRCODE_IO_CANTREAD
;
1710 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1712 catch ( const ::com::sun::star::uno::Exception
& )
1714 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1719 if ( pImp
->pTempFile
)
1721 pImp
->pTempFile
->EnableKillingFile( true );
1722 delete pImp
->pTempFile
;
1723 pImp
->pTempFile
= NULL
;
1726 else if ( bTransactStarted
)
1728 UseBackupToRestore_Impl( aOriginalContent
, xDummyEnv
);
1732 pImp
->m_eError
= ERRCODE_IO_CANTREAD
;
1738 //------------------------------------------------------------------
1739 sal_Bool
SfxMedium::TryDirectTransfer( const OUString
& aURL
, SfxItemSet
& aTargetSet
)
1744 // if the document had no password it should be stored without password
1745 // if the document had password it should be stored with the same password
1746 // otherwise the stream copying can not be done
1747 SFX_ITEMSET_ARG( &aTargetSet
, pNewPassItem
, SfxStringItem
, SID_PASSWORD
, false );
1748 SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem
, SfxStringItem
, SID_PASSWORD
, false );
1749 if ( ( !pNewPassItem
&& !pOldPassItem
)
1750 || ( pNewPassItem
&& pOldPassItem
&& pNewPassItem
->GetValue() == pOldPassItem
->GetValue() ) )
1752 // the filter must be the same
1753 SFX_ITEMSET_ARG( &aTargetSet
, pNewFilterItem
, SfxStringItem
, SID_FILTER_NAME
, false );
1754 SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem
, SfxStringItem
, SID_FILTER_NAME
, false );
1755 if ( pNewFilterItem
&& pOldFilterItem
&& pNewFilterItem
->GetValue() == pOldFilterItem
->GetValue() )
1757 // get the input stream and copy it
1758 // in case of success return true
1759 uno::Reference
< io::XInputStream
> xInStream
= GetInputStream();
1762 if ( xInStream
.is() )
1766 uno::Reference
< io::XSeekable
> xSeek( xInStream
, uno::UNO_QUERY
);
1770 nPos
= xSeek
->getPosition();
1774 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
1775 ::ucbhelper::Content
aTargetContent( aURL
, xEnv
, comphelper::getProcessComponentContext() );
1777 InsertCommandArgument aInsertArg
;
1778 aInsertArg
.Data
= xInStream
;
1779 SFX_ITEMSET_ARG( &aTargetSet
, pRename
, SfxBoolItem
, SID_RENAME
, false );
1780 SFX_ITEMSET_ARG( &aTargetSet
, pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, false );
1781 if ( (pOverWrite
&& !pOverWrite
->GetValue()) // argument says: never overwrite
1782 || (pRename
&& pRename
->GetValue()) ) // argument says: rename file
1783 aInsertArg
.ReplaceExisting
= false;
1785 aInsertArg
.ReplaceExisting
= true; // default is overwrite existing files
1788 aCmdArg
<<= aInsertArg
;
1789 aTargetContent
.executeCommand( OUString( "insert" ),
1793 xSeek
->seek( nPos
);
1797 catch( const uno::Exception
& )
1806 //------------------------------------------------------------------
1807 void SfxMedium::Transfer_Impl()
1809 // The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
1811 if ( pImp
->pTempFile
)
1812 aNameURL
= pImp
->pTempFile
->GetURL();
1813 else if ( !pImp
->m_aLogicName
.isEmpty() && pImp
->m_bSalvageMode
)
1815 // makes sence only in case logic name is set
1816 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aNameURL
) )
1817 OSL_FAIL( "The medium name is not convertible!\n" );
1820 if ( !aNameURL
.isEmpty() && ( !pImp
->m_eError
|| (pImp
->m_eError
& ERRCODE_WARNING_MASK
) ) )
1822 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::Transfer_Impl, copying to target" );
1824 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
1825 Reference
< XOutputStream
> rOutStream
;
1827 // in case an output stream is provided from outside and the URL is correct
1828 // commit to the stream
1829 if (pImp
->m_aLogicName
.startsWith("private:stream"))
1831 // TODO/LATER: support storing to SID_STREAM
1832 SFX_ITEMSET_ARG( pImp
->m_pSet
, pOutStreamItem
, SfxUnoAnyItem
, SID_OUTPUTSTREAM
, false);
1833 if( pOutStreamItem
&& ( pOutStreamItem
->GetValue() >>= rOutStream
) )
1835 if ( pImp
->xStorage
.is() )
1838 CloseStreams_Impl();
1840 INetURLObject
aSource( aNameURL
);
1841 ::ucbhelper::Content aTempCont
;
1842 if( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext(), aTempCont
) )
1847 sal_Int32 nBufferSize
= 32767;
1848 Sequence
< sal_Int8
> aSequence ( nBufferSize
);
1849 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1853 nRead
= aTempInput
->readBytes ( aSequence
, nBufferSize
);
1854 if ( nRead
< nBufferSize
)
1856 Sequence
< sal_Int8
> aTempBuf ( aSequence
.getConstArray(), nRead
);
1857 rOutStream
->writeBytes ( aTempBuf
);
1860 rOutStream
->writeBytes ( aSequence
);
1862 while ( nRead
== nBufferSize
);
1864 // remove temporary file
1865 if ( pImp
->pTempFile
)
1867 pImp
->pTempFile
->EnableKillingFile( true );
1868 delete pImp
->pTempFile
;
1869 pImp
->pTempFile
= NULL
;
1872 catch( const Exception
& )
1878 OSL_FAIL( "Illegal Output stream parameter!\n" );
1879 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1882 // free the reference
1884 pImp
->m_pSet
->ClearItem( SID_OUTPUTSTREAM
);
1890 if ( !pImp
->aContent
.get().is() )
1892 pImp
->m_eError
= ERRCODE_IO_NOTEXISTS
;
1896 SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize
, SfxInt32Item
, SID_SEGMENTSIZE
, false);
1899 // this file must be stored into a disk spanned package
1902 uno::Reference
< embed::XStorage
> xStor
= comphelper::OStorageHelper::GetStorageFromURL( GetName(),
1903 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1905 // set segment size property; package will automatically be divided in pieces fitting
1907 ::com::sun::star::uno::Any aAny
;
1908 aAny
<<= pSegmentSize
->GetValue();
1910 uno::Reference
< beans::XPropertySet
> xSet( pImp
->xStorage
, uno::UNO_QUERY
);
1911 xSet
->setPropertyValue( OUString("SegmentSize"), aAny
);
1913 // copy the temporary storage into the disk spanned package
1914 GetStorage()->copyToStorage( xStor
);
1915 uno::Reference
< embed::XTransactedObject
> xTrans( pImp
->xStorage
, uno::UNO_QUERY
);
1920 catch ( const uno::Exception
& )
1922 //TODO/MBA: error handling
1927 INetURLObject
aDest( GetURLObject() );
1929 // source is the temp file written so far
1930 INetURLObject
aSource( aNameURL
);
1932 // a special case, an interaction handler should be used for
1933 // authentication in case it is available
1934 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
1935 Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler
= GetInteractionHandler();
1936 if (xInteractionHandler
.is())
1937 xComEnv
= new ::ucbhelper::CommandEnvironment( xInteractionHandler
,
1938 Reference
< ::com::sun::star::ucb::XProgressHandler
>() );
1940 OUString
aDestURL( aDest
.GetMainURL( INetURLObject::NO_DECODE
) );
1942 if ( ::utl::LocalFileHelper::IsLocalFile( aDestURL
) || !aDest
.removeSegment() )
1944 TransactedTransferForFS_Impl( aSource
, aDest
, xComEnv
);
1946 // Hideous - no clean way to do this, so we re-open the file just to fsync it
1947 osl::File
aFile( aDestURL
);
1948 if ( aFile
.open( osl_File_OpenFlag_Write
) == osl::FileBase::E_None
)
1951 OSL_TRACE("fsync'd saved file '%s'\n",
1952 OUStringToOString( aDestURL
, RTL_TEXTENCODING_UTF8
).getStr() );
1958 // create content for the parent folder and call transfer on that content with the source content
1959 // and the destination file name as parameters
1960 ::ucbhelper::Content aSourceContent
;
1961 ::ucbhelper::Content aTransferContent
;
1963 ::ucbhelper::Content aDestContent
;
1964 ::ucbhelper::Content::create( aDestURL
, xComEnv
, comphelper::getProcessComponentContext(), aDestContent
);
1965 // For checkin, we need the object URL, not the parent folder:
1966 if ( !IsInCheckIn( ) )
1968 // Get the parent URL from the XChild if possible: why would the URL necessarily have
1969 // a hierarchical path? It's not always the case for CMIS.
1970 Reference
< ::com::sun::star::container::XChild
> xChild( aDestContent
.get(), uno::UNO_QUERY
);
1971 OUString sParentUrl
;
1974 Reference
< ::com::sun::star::ucb::XContent
> xParent( xChild
->getParent( ), uno::UNO_QUERY
);
1975 if ( xParent
.is( ) )
1977 sParentUrl
= xParent
->getIdentifier( )->getContentIdentifier();
1981 if ( sParentUrl
.isEmpty() )
1982 aDestURL
= aDest
.GetMainURL( INetURLObject::NO_DECODE
);
1983 // adjust to above aDest.removeSegment()
1985 aDestURL
= sParentUrl
;
1988 // LongName wasn't defined anywhere, only used here... get the Title instead
1989 // as it's less probably empty
1991 Any aAny
= aDestContent
.getPropertyValue( OUString("Title" ) );
1993 if ( aFileName
.isEmpty() )
1994 aFileName
= GetURLObject().getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
1998 aTransferContent
= ::ucbhelper::Content( aDestURL
, xComEnv
, comphelper::getProcessComponentContext() );
2000 catch (const ::com::sun::star::ucb::ContentCreationException
& ex
)
2002 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2004 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER
) ||
2005 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED
)
2008 pImp
->m_eError
= ERRCODE_IO_NOTEXISTSPATH
;
2011 catch (const ::com::sun::star::uno::Exception
&)
2013 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2016 if ( !pImp
->m_eError
|| (pImp
->m_eError
& ERRCODE_WARNING_MASK
) )
2018 // free resources, otherwise the transfer may fail
2019 if ( pImp
->xStorage
.is() )
2022 CloseStreams_Impl();
2024 ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext(), aSourceContent
);
2026 // check for external parameters that may customize the handling of NameClash situations
2027 SFX_ITEMSET_ARG( GetItemSet(), pRename
, SfxBoolItem
, SID_RENAME
, false );
2028 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, false );
2029 sal_Int32 nNameClash
;
2030 if ( pOverWrite
&& !pOverWrite
->GetValue() )
2031 // argument says: never overwrite
2032 nNameClash
= NameClash::ERROR
;
2033 else if ( pRename
&& pRename
->GetValue() )
2034 // argument says: rename file
2035 nNameClash
= NameClash::RENAME
;
2037 // default is overwrite existing files
2038 nNameClash
= NameClash::OVERWRITE
;
2042 OUString aMimeType
= pImp
->getFilterMimeType();
2043 ::ucbhelper::InsertOperation eOperation
= ::ucbhelper::InsertOperation_COPY
;
2044 bool bMajor
= false;
2046 if ( IsInCheckIn( ) )
2048 eOperation
= ::ucbhelper::InsertOperation_CHECKIN
;
2049 SFX_ITEMSET_ARG( GetItemSet(), pMajor
, SfxBoolItem
, SID_DOCINFO_MAJOR
, false );
2050 bMajor
= pMajor
&& pMajor
->GetValue( );
2051 SFX_ITEMSET_ARG( GetItemSet(), pComments
, SfxStringItem
, SID_DOCINFO_COMMENTS
, false );
2053 sComment
= pComments
->GetValue( );
2055 OUString sResultURL
;
2056 if (!aTransferContent
.transferContent( aSourceContent
, eOperation
,
2057 aFileName
, nNameClash
, aMimeType
, bMajor
, sComment
, &sResultURL
))
2058 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2059 else if ( !sResultURL
.isEmpty( ) ) // Likely to happen only for checkin
2060 SwitchDocumentToFile( sResultURL
);
2062 catch ( const ::com::sun::star::ucb::CommandAbortedException
& )
2064 pImp
->m_eError
= ERRCODE_ABORT
;
2066 catch ( const ::com::sun::star::ucb::CommandFailedException
& )
2068 pImp
->m_eError
= ERRCODE_ABORT
;
2070 catch ( const ::com::sun::star::ucb::InteractiveIOException
& r
)
2072 if ( r
.Code
== IOErrorCode_ACCESS_DENIED
)
2073 pImp
->m_eError
= ERRCODE_IO_ACCESSDENIED
;
2074 else if ( r
.Code
== IOErrorCode_NOT_EXISTING
)
2075 pImp
->m_eError
= ERRCODE_IO_NOTEXISTS
;
2076 else if ( r
.Code
== IOErrorCode_CANT_READ
)
2077 pImp
->m_eError
= ERRCODE_IO_CANTREAD
;
2079 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2081 catch ( const ::com::sun::star::uno::Exception
& )
2083 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2086 // do not switch from temporary file in case of nonfile protocol
2090 if ( ( !pImp
->m_eError
|| (pImp
->m_eError
& ERRCODE_WARNING_MASK
) ) && !pImp
->pTempFile
)
2092 // without a TempFile the physical and logical name should be the same after successful transfer
2093 ::utl::LocalFileHelper::ConvertURLToPhysicalName(
2094 GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), pImp
->m_aName
);
2095 pImp
->m_bSalvageMode
= false;
2100 //------------------------------------------------------------------
2101 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content
& aOriginalContent
,
2102 const String
& aPrefix
,
2103 const String
& aExtension
,
2104 const String
& aDestDir
)
2106 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::DoInternalBackup_Impl( with destdir )" );
2108 if ( !pImp
->m_aBackupURL
.isEmpty() )
2109 return; // the backup was done already
2111 ::utl::TempFile
aTransactTemp( aPrefix
, &aExtension
, &aDestDir
);
2112 aTransactTemp
.EnableKillingFile( false );
2114 INetURLObject
aBackObj( aTransactTemp
.GetURL() );
2115 OUString aBackupName
= aBackObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2117 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
2118 ::ucbhelper::Content aBackupCont
;
2119 if( ::ucbhelper::Content::create( aDestDir
, xDummyEnv
, comphelper::getProcessComponentContext(), aBackupCont
) )
2123 OUString sMimeType
= pImp
->getFilterMimeType();
2124 if( aBackupCont
.transferContent( aOriginalContent
,
2125 ::ucbhelper::InsertOperation_COPY
,
2127 NameClash::OVERWRITE
,
2130 pImp
->m_aBackupURL
= aBackObj
.GetMainURL( INetURLObject::NO_DECODE
);
2131 pImp
->m_bRemoveBackup
= true;
2134 catch( const Exception
& )
2138 if ( pImp
->m_aBackupURL
.isEmpty() )
2139 aTransactTemp
.EnableKillingFile( true );
2142 //------------------------------------------------------------------
2143 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content
& aOriginalContent
)
2145 if ( !pImp
->m_aBackupURL
.isEmpty() )
2146 return; // the backup was done already
2148 OUString aFileName
= GetURLObject().getName( INetURLObject::LAST_SEGMENT
,
2150 INetURLObject::NO_DECODE
);
2152 sal_Int32 nPrefixLen
= aFileName
.lastIndexOf( '.' );
2153 String aPrefix
= ( nPrefixLen
== -1 ) ? aFileName
: aFileName
.copy( 0, nPrefixLen
);
2154 String aExtension
= ( nPrefixLen
== -1 ) ? String() : String(aFileName
.copy( nPrefixLen
));
2155 String aBakDir
= SvtPathOptions().GetBackupPath();
2157 // create content for the parent folder ( = backup folder )
2158 ::ucbhelper::Content aContent
;
2159 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
2160 if( ::utl::UCBContentHelper::ensureFolder(comphelper::getProcessComponentContext(), xEnv
, aBakDir
, aContent
) )
2161 DoInternalBackup_Impl( aOriginalContent
, aPrefix
, aExtension
, aBakDir
);
2163 if ( pImp
->m_aBackupURL
.isEmpty() )
2165 // the copiing to the backup catalog failed ( for example because
2166 // of using an encrypted partition as target catalog )
2167 // since the user did not specify to make backup explicitly
2168 // office should try to make backup in another place,
2169 // target catalog does not look bad for this case ( and looks
2170 // to be the only way for encrypted partitions )
2172 INetURLObject aDest
= GetURLObject();
2173 if ( aDest
.removeSegment() )
2174 DoInternalBackup_Impl( aOriginalContent
, aPrefix
, aExtension
, aDest
.GetMainURL( INetURLObject::NO_DECODE
) );
2179 //------------------------------------------------------------------
2180 void SfxMedium::DoBackup_Impl()
2182 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::DoBackup_Impl" );
2184 // source file name is the logical name of this medium
2185 INetURLObject
aSource( GetURLObject() );
2187 // there is nothing to backup in case source file does not exist
2188 if ( !::utl::UCBContentHelper::IsDocument( aSource
.GetMainURL( INetURLObject::NO_DECODE
) ) )
2191 bool bSuccess
= false;
2193 // get path for backups
2194 String aBakDir
= SvtPathOptions().GetBackupPath();
2197 // create content for the parent folder ( = backup folder )
2198 ::ucbhelper::Content aContent
;
2199 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
2200 if( ::utl::UCBContentHelper::ensureFolder(comphelper::getProcessComponentContext(), xEnv
, aBakDir
, aContent
) )
2202 // save as ".bak" file
2203 INetURLObject
aDest( aBakDir
);
2204 aDest
.insertName( aSource
.getName() );
2205 aDest
.setExtension( "bak" );
2206 String aFileName
= aDest
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2208 // create a content for the source file
2209 ::ucbhelper::Content aSourceContent
;
2210 if ( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext(), aSourceContent
) )
2214 // do the transfer ( copy source file to backup dir )
2215 OUString sMimeType
= pImp
->getFilterMimeType();
2216 bSuccess
= aContent
.transferContent( aSourceContent
,
2217 ::ucbhelper::InsertOperation_COPY
,
2219 NameClash::OVERWRITE
,
2223 pImp
->m_aBackupURL
= aDest
.GetMainURL( INetURLObject::NO_DECODE
);
2224 pImp
->m_bRemoveBackup
= false;
2227 catch ( const ::com::sun::star::uno::Exception
& )
2236 pImp
->m_eError
= ERRCODE_SFX_CANTCREATEBACKUP
;
2240 //------------------------------------------------------------------
2241 void SfxMedium::ClearBackup_Impl()
2243 if( pImp
->m_bRemoveBackup
)
2245 // currently a document is always stored in a new medium,
2246 // thus if a backup can not be removed the backup URL should not be cleaned
2247 if ( !pImp
->m_aBackupURL
.isEmpty() )
2249 if ( ::utl::UCBContentHelper::Kill( pImp
->m_aBackupURL
) )
2251 pImp
->m_bRemoveBackup
= false;
2252 pImp
->m_aBackupURL
= OUString();
2257 OSL_FAIL("Couldn't remove backup file!");
2262 pImp
->m_aBackupURL
= OUString();
2265 //----------------------------------------------------------------
2266 void SfxMedium::GetLockingStream_Impl()
2268 if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
2269 && !pImp
->m_xLockingStream
.is() )
2271 SFX_ITEMSET_ARG( pImp
->m_pSet
, pWriteStreamItem
, SfxUnoAnyItem
, SID_STREAM
, false);
2272 if ( pWriteStreamItem
)
2273 pWriteStreamItem
->GetValue() >>= pImp
->m_xLockingStream
;
2275 if ( !pImp
->m_xLockingStream
.is() )
2277 // open the original document
2278 uno::Sequence
< beans::PropertyValue
> xProps
;
2279 TransformItems( SID_OPENDOC
, *GetItemSet(), xProps
);
2280 comphelper::MediaDescriptor
aMedium( xProps
);
2282 aMedium
.addInputStreamOwnLock();
2284 uno::Reference
< io::XInputStream
> xInputStream
;
2285 aMedium
[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp
->m_xLockingStream
;
2286 aMedium
[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream
;
2288 if ( !pImp
->pTempFile
&& pImp
->m_aName
.isEmpty() )
2290 // the medium is still based on the original file, it makes sence to initialize the streams
2291 if ( pImp
->m_xLockingStream
.is() )
2292 pImp
->xStream
= pImp
->m_xLockingStream
;
2294 if ( xInputStream
.is() )
2295 pImp
->xInputStream
= xInputStream
;
2297 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2298 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2304 //----------------------------------------------------------------
2305 void SfxMedium::GetMedium_Impl()
2307 if ( !pImp
->m_pInStream
)
2309 pImp
->bDownloadDone
= false;
2310 Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler
= GetInteractionHandler();
2312 //TODO/MBA: need support for SID_STREAM
2313 SFX_ITEMSET_ARG( pImp
->m_pSet
, pWriteStreamItem
, SfxUnoAnyItem
, SID_STREAM
, false);
2314 SFX_ITEMSET_ARG( pImp
->m_pSet
, pInStreamItem
, SfxUnoAnyItem
, SID_INPUTSTREAM
, false);
2315 if ( pWriteStreamItem
)
2317 pWriteStreamItem
->GetValue() >>= pImp
->xStream
;
2319 if ( pInStreamItem
)
2320 pInStreamItem
->GetValue() >>= pImp
->xInputStream
;
2322 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2323 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2325 else if ( pInStreamItem
)
2327 pInStreamItem
->GetValue() >>= pImp
->xInputStream
;
2331 uno::Sequence
< beans::PropertyValue
> xProps
;
2333 if (!pImp
->m_aName
.isEmpty())
2335 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aFileName
) )
2337 OSL_FAIL("Physical name not convertible!");
2341 aFileName
= GetName();
2343 // in case the temporary file exists the streams should be initialized from it,
2344 // but the original MediaDescriptor should not be changed
2345 bool bFromTempFile
= ( pImp
->pTempFile
!= NULL
);
2347 if ( !bFromTempFile
)
2349 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, aFileName
) );
2350 if( !(pImp
->m_nStorOpenMode
& STREAM_WRITE
) )
2351 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
2352 if (xInteractionHandler
.is())
2353 GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER
, makeAny(xInteractionHandler
) ) );
2356 if ( pImp
->m_xInputStreamToLoadFrom
.is() )
2358 pImp
->xInputStream
= pImp
->m_xInputStreamToLoadFrom
;
2359 pImp
->xInputStream
->skipBytes(0);
2360 if (pImp
->m_bInputStreamIsReadOnly
)
2361 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
2365 TransformItems( SID_OPENDOC
, *GetItemSet(), xProps
);
2366 comphelper::MediaDescriptor
aMedium( xProps
);
2368 if ( pImp
->m_xLockingStream
.is() && !bFromTempFile
)
2370 // the medium is not based on the temporary file, so the original stream can be used
2371 pImp
->xStream
= pImp
->m_xLockingStream
;
2375 if ( bFromTempFile
)
2377 aMedium
[comphelper::MediaDescriptor::PROP_URL()] <<= OUString( aFileName
);
2378 aMedium
.erase( comphelper::MediaDescriptor::PROP_READONLY() );
2379 aMedium
.addInputStream();
2381 else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
2383 // use the special locking approach only for file URLs
2384 aMedium
.addInputStreamOwnLock();
2387 aMedium
.addInputStream();
2389 // the ReadOnly property set in aMedium is ignored
2390 // the check is done in LockOrigFileOnDemand() for file and non-file URLs
2392 //TODO/MBA: what happens if property is not there?!
2393 aMedium
[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp
->xStream
;
2394 aMedium
[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp
->xInputStream
;
2398 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2399 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2402 if ( !bFromTempFile
)
2404 //TODO/MBA: need support for SID_STREAM
2405 if ( pImp
->xStream
.is() )
2406 GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM
, makeAny( pImp
->xStream
) ) );
2408 GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM
, makeAny( pImp
->xInputStream
) ) );
2412 //TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
2413 if ( !GetError() && !pImp
->xStream
.is() && !pImp
->xInputStream
.is() )
2414 SetError( ERRCODE_IO_ACCESSDENIED
, OUString( OSL_LOG_PREFIX
) );
2418 if ( pImp
->xStream
.is() )
2419 pImp
->m_pInStream
= utl::UcbStreamHelper::CreateStream( pImp
->xStream
);
2420 else if ( pImp
->xInputStream
.is() )
2421 pImp
->m_pInStream
= utl::UcbStreamHelper::CreateStream( pImp
->xInputStream
);
2424 pImp
->bDownloadDone
= true;
2425 pImp
->aDoneLink
.ClearPendingCall();
2426 sal_uIntPtr nError
= GetError();
2427 pImp
->aDoneLink
.Call( (void*)nError
);
2431 //----------------------------------------------------------------
2432 sal_Bool
SfxMedium::IsRemote()
2434 return pImp
->m_bRemote
;
2437 //------------------------------------------------------------------
2439 void SfxMedium::SetUpdatePickList(sal_Bool bVal
)
2441 pImp
->bUpdatePickList
= bVal
;
2443 //------------------------------------------------------------------
2445 sal_Bool
SfxMedium::IsUpdatePickList() const
2447 return pImp
->bUpdatePickList
;
2450 void SfxMedium::SetLongName(const OUString
&rName
)
2452 pImp
->m_aLongName
= rName
;
2455 const OUString
& SfxMedium::GetLongName() const
2457 return pImp
->m_aLongName
;
2460 void SfxMedium::SetDoneLink( const Link
& rLink
)
2462 pImp
->aDoneLink
= rLink
;
2465 void SfxMedium::DownLoad( const Link
& aLink
)
2467 SetDoneLink( aLink
);
2469 if ( pImp
->m_pInStream
&& !aLink
.IsSet() )
2471 while( !pImp
->bDownloadDone
)
2472 Application::Yield();
2476 //------------------------------------------------------------------
2477 void SfxMedium::Init_Impl()
2479 Includes a valid:: sun:: com:: star:: util:: URL (If a file name was
2480 previously in there) in the logical name and if available sets the
2481 physical name as the file name.
2485 Reference
< XOutputStream
> rOutStream
;
2487 // TODO/LATER: handle lifetime of storages
2488 pImp
->bDisposeStorage
= false;
2490 SFX_ITEMSET_ARG( pImp
->m_pSet
, pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, false);
2491 if ( pSalvageItem
&& pSalvageItem
->GetValue().isEmpty() )
2493 pSalvageItem
= NULL
;
2494 pImp
->m_pSet
->ClearItem( SID_DOC_SALVAGE
);
2497 if (!pImp
->m_aLogicName
.isEmpty())
2499 INetURLObject
aUrl( pImp
->m_aLogicName
);
2500 INetProtocol eProt
= aUrl
.GetProtocol();
2501 if ( eProt
== INET_PROT_NOT_VALID
)
2503 OSL_FAIL( "Unknown protocol!" );
2507 if ( aUrl
.HasMark() )
2509 pImp
->m_aLogicName
= aUrl
.GetURLNoMark( INetURLObject::NO_DECODE
);
2510 GetItemSet()->Put( SfxStringItem( SID_JUMPMARK
, aUrl
.GetMark() ) );
2513 // try to convert the URL into a physical name - but never change a physical name
2514 // physical name may be set if the logical name is changed after construction
2515 if ( pImp
->m_aName
.isEmpty() )
2516 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), pImp
->m_aName
);
2519 DBG_ASSERT( pSalvageItem
, "Suspicious change of logical name!" );
2524 if ( pSalvageItem
&& !pSalvageItem
->GetValue().isEmpty() )
2526 pImp
->m_aLogicName
= pSalvageItem
->GetValue();
2527 DELETEZ( pImp
->m_pURLObj
);
2528 pImp
->m_bSalvageMode
= true;
2531 // in case output stream is by mistake here
2532 // clear the reference
2533 SFX_ITEMSET_ARG( pImp
->m_pSet
, pOutStreamItem
, SfxUnoAnyItem
, SID_OUTPUTSTREAM
, false);
2535 && ( !( pOutStreamItem
->GetValue() >>= rOutStream
)
2536 || !pImp
->m_aLogicName
.startsWith("private:stream")) )
2538 pImp
->m_pSet
->ClearItem( SID_OUTPUTSTREAM
);
2539 OSL_FAIL( "Unexpected Output stream parameter!\n" );
2542 if (!pImp
->m_aLogicName
.isEmpty())
2544 // if the logic name is set it should be set in MediaDescriptor as well
2545 SFX_ITEMSET_ARG( pImp
->m_pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, false );
2546 if ( !pFileNameItem
)
2548 // let the ItemSet be created if necessary
2551 SID_FILE_NAME
, INetURLObject( pImp
->m_aLogicName
).GetMainURL( INetURLObject::NO_DECODE
) ) );
2558 //------------------------------------------------------------------
2559 SfxMedium::SfxMedium() : pImp(new SfxMedium_Impl(this))
2564 //------------------------------------------------------------------
2566 void SfxMedium::UseInteractionHandler( sal_Bool bUse
)
2568 pImp
->bAllowDefaultIntHdl
= bUse
;
2571 //------------------------------------------------------------------
2573 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>
2574 SfxMedium::GetInteractionHandler()
2576 // if interaction isnt allowed explicitly ... return empty reference!
2577 if ( !pImp
->bUseInteractionHandler
)
2578 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2580 // search a possible existing handler inside cached item set
2583 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
> xHandler
;
2584 SFX_ITEMSET_ARG( pImp
->m_pSet
, pHandler
, SfxUnoAnyItem
, SID_INTERACTIONHANDLER
, false);
2585 if ( pHandler
&& (pHandler
->GetValue() >>= xHandler
) && xHandler
.is() )
2589 // if default interaction isnt allowed explicitly ... return empty reference!
2590 if ( !pImp
->bAllowDefaultIntHdl
)
2591 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2593 // otherwise return cached default handler ... if it exist.
2594 if ( pImp
->xInteraction
.is() )
2595 return pImp
->xInteraction
;
2597 // create default handler and cache it!
2598 Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2599 pImp
->xInteraction
.set(
2600 task::InteractionHandler::createWithParent(xContext
, 0), UNO_QUERY_THROW
);
2601 return pImp
->xInteraction
;
2604 //----------------------------------------------------------------
2606 void SfxMedium::SetFilter( const SfxFilter
* pFilterP
, sal_Bool
/*bResetOrig*/ )
2608 pImp
->m_pFilter
= pFilterP
;
2611 const SfxFilter
* SfxMedium::GetFilter() const
2613 return pImp
->m_pFilter
;
2616 //----------------------------------------------------------------
2618 const SfxFilter
* SfxMedium::GetOrigFilter( sal_Bool bNotCurrent
) const
2620 return ( pImp
->pOrigFilter
|| bNotCurrent
) ? pImp
->pOrigFilter
: pImp
->m_pFilter
;
2623 //----------------------------------------------------------------
2625 sal_uInt32
SfxMedium::CreatePasswordToModifyHash( const OUString
& aPasswd
, sal_Bool bWriter
)
2627 sal_uInt32 nHash
= 0;
2629 if ( !aPasswd
.isEmpty() )
2633 nHash
= ::comphelper::DocPasswordHelper::GetWordHashAsUINT32( aPasswd
);
2637 rtl_TextEncoding nEncoding
= osl_getThreadTextEncoding();
2638 nHash
= ::comphelper::DocPasswordHelper::GetXLHashAsUINT16( aPasswd
, nEncoding
);
2645 //------------------------------------------------------------------
2647 void SfxMedium::Close()
2649 if ( pImp
->xStorage
.is() )
2654 CloseStreams_Impl();
2656 UnlockFile( false );
2659 void SfxMedium::CloseAndRelease()
2661 if ( pImp
->xStorage
.is() )
2666 CloseAndReleaseStreams_Impl();
2671 void SfxMedium::UnlockFile( sal_Bool bReleaseLockStream
)
2673 #if !HAVE_FEATURE_MULTIUSER_ENVIRONMENT
2674 (void) bReleaseLockStream
;
2676 if ( pImp
->m_xLockingStream
.is() )
2678 if ( bReleaseLockStream
)
2682 uno::Reference
< io::XInputStream
> xInStream
= pImp
->m_xLockingStream
->getInputStream();
2683 uno::Reference
< io::XOutputStream
> xOutStream
= pImp
->m_xLockingStream
->getOutputStream();
2684 if ( xInStream
.is() )
2685 xInStream
->closeInput();
2686 if ( xOutStream
.is() )
2687 xOutStream
->closeOutput();
2689 catch( const uno::Exception
& )
2693 pImp
->m_xLockingStream
.clear();
2696 if ( pImp
->m_bLocked
)
2700 pImp
->m_bLocked
= false;
2701 ::svt::DocumentLockFile
aLockFile( pImp
->m_aLogicName
);
2702 // TODO/LATER: A warning could be shown in case the file is not the own one
2703 aLockFile
.RemoveFile();
2705 catch( const uno::Exception
& )
2711 void SfxMedium::CloseAndReleaseStreams_Impl()
2713 CloseZipStorage_Impl();
2715 uno::Reference
< io::XInputStream
> xInToClose
= pImp
->xInputStream
;
2716 uno::Reference
< io::XOutputStream
> xOutToClose
;
2717 if ( pImp
->xStream
.is() )
2719 xOutToClose
= pImp
->xStream
->getOutputStream();
2721 // if the locking stream is closed here the related member should be cleaned
2722 if ( pImp
->xStream
== pImp
->m_xLockingStream
)
2723 pImp
->m_xLockingStream
.clear();
2726 // The probably exsisting SvStream wrappers should be closed first
2727 CloseStreams_Impl();
2729 // in case of salvage mode the storage is based on the streams
2730 if ( !pImp
->m_bSalvageMode
)
2734 if ( xInToClose
.is() )
2735 xInToClose
->closeInput();
2736 if ( xOutToClose
.is() )
2737 xOutToClose
->closeOutput();
2739 catch ( const uno::Exception
& )
2745 //------------------------------------------------------------------
2746 void SfxMedium::CloseStreams_Impl()
2748 CloseInStream_Impl();
2749 CloseOutStream_Impl();
2752 pImp
->m_pSet
->ClearItem( SID_CONTENT
);
2754 pImp
->aContent
= ::ucbhelper::Content();
2757 //------------------------------------------------------------------
2759 void SfxMedium::SetIsRemote_Impl()
2761 INetURLObject
aObj( GetName() );
2762 switch( aObj
.GetProtocol() )
2765 case INET_PROT_HTTP
:
2766 case INET_PROT_HTTPS
:
2767 case INET_PROT_POP3
:
2768 case INET_PROT_NEWS
:
2769 case INET_PROT_IMAP
:
2771 pImp
->m_bRemote
= true;
2774 pImp
->m_bRemote
= GetName().startsWith("private:msgid");
2778 // As files that are written to the remote transmission must also be able
2780 if (pImp
->m_bRemote
)
2781 pImp
->m_nStorOpenMode
|= STREAM_READ
;
2786 void SfxMedium::SetName( const String
& aNameP
, sal_Bool bSetOrigURL
)
2788 if (pImp
->aOrigURL
.isEmpty())
2789 pImp
->aOrigURL
= pImp
->m_aLogicName
;
2791 pImp
->aOrigURL
= aNameP
;
2792 pImp
->m_aLogicName
= aNameP
;
2793 DELETEZ( pImp
->m_pURLObj
);
2794 pImp
->aContent
= ::ucbhelper::Content();
2798 //----------------------------------------------------------------
2799 const OUString
& SfxMedium::GetOrigURL() const
2801 return pImp
->aOrigURL
.isEmpty() ? pImp
->m_aLogicName
: pImp
->aOrigURL
;
2804 //----------------------------------------------------------------
2806 void SfxMedium::SetPhysicalName_Impl( const OUString
& rNameP
)
2808 if ( rNameP
!= pImp
->m_aName
)
2810 if( pImp
->pTempFile
)
2812 delete pImp
->pTempFile
;
2813 pImp
->pTempFile
= NULL
;
2816 if ( !pImp
->m_aName
.isEmpty() || !rNameP
.isEmpty() )
2817 pImp
->aContent
= ::ucbhelper::Content();
2819 pImp
->m_aName
= rNameP
;
2820 pImp
->m_bTriedStorage
= false;
2821 pImp
->bIsStorage
= false;
2825 //------------------------------------------------------------------
2827 void SfxMedium::ReOpen()
2829 bool bUseInteractionHandler
= pImp
->bUseInteractionHandler
;
2830 pImp
->bUseInteractionHandler
= false;
2832 pImp
->bUseInteractionHandler
= bUseInteractionHandler
;
2835 //------------------------------------------------------------------
2837 void SfxMedium::CompleteReOpen()
2839 // do not use temporary file for reopen and in case of success throw the temporary file away
2840 bool bUseInteractionHandler
= pImp
->bUseInteractionHandler
;
2841 pImp
->bUseInteractionHandler
= false;
2843 ::utl::TempFile
* pTmpFile
= NULL
;
2844 if ( pImp
->pTempFile
)
2846 pTmpFile
= pImp
->pTempFile
;
2847 pImp
->pTempFile
= NULL
;
2848 pImp
->m_aName
= OUString();
2855 if ( pImp
->pTempFile
)
2857 pImp
->pTempFile
->EnableKillingFile( true );
2858 delete pImp
->pTempFile
;
2860 pImp
->pTempFile
= pTmpFile
;
2861 if ( pImp
->pTempFile
)
2862 pImp
->m_aName
= pImp
->pTempFile
->GetFileName();
2866 pTmpFile
->EnableKillingFile( true );
2871 pImp
->bUseInteractionHandler
= bUseInteractionHandler
;
2874 SfxMedium::SfxMedium(const String
&rName
, StreamMode nOpenMode
, const SfxFilter
*pFlt
, SfxItemSet
*pInSet
) :
2875 pImp(new SfxMedium_Impl(this))
2877 pImp
->m_pSet
= pInSet
;
2878 pImp
->m_pFilter
= pFlt
;
2879 pImp
->m_aLogicName
= rName
;
2880 pImp
->m_nStorOpenMode
= nOpenMode
;
2884 SfxMedium::SfxMedium( const uno::Sequence
<beans::PropertyValue
>& aArgs
) :
2885 pImp(new SfxMedium_Impl(this))
2887 SfxAllItemSet
*pParams
= new SfxAllItemSet( SFX_APP()->GetPool() );
2888 pImp
->m_pSet
= pParams
;
2889 TransformParameters( SID_OPENDOC
, aArgs
, *pParams
);
2891 OUString aFilterProvider
, aFilterName
;
2893 const SfxPoolItem
* pItem
= NULL
;
2894 if (pImp
->m_pSet
->HasItem(SID_FILTER_PROVIDER
, &pItem
))
2895 aFilterProvider
= static_cast<const SfxStringItem
*>(pItem
)->GetValue();
2897 if (pImp
->m_pSet
->HasItem(SID_FILTER_NAME
, &pItem
))
2898 aFilterName
= static_cast<const SfxStringItem
*>(pItem
)->GetValue();
2901 if (aFilterProvider
.isEmpty())
2903 // This is a conventional filter type.
2904 pImp
->m_pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4FilterName( aFilterName
);
2908 // This filter is from an external provider such as orcus.
2909 pImp
->m_pCustomFilter
.reset(new SfxFilter(aFilterProvider
, aFilterName
));
2910 pImp
->m_pFilter
= pImp
->m_pCustomFilter
.get();
2913 SFX_ITEMSET_ARG( pImp
->m_pSet
, pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, false );
2916 // QUESTION: there is some treatment of Salvage in Init_Impl; align!
2917 if ( !pSalvageItem
->GetValue().isEmpty() )
2919 // if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
2920 // that must be copied here
2922 SFX_ITEMSET_ARG( pImp
->m_pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, false );
2923 if (!pFileNameItem
) throw uno::RuntimeException();
2924 OUString aNewTempFileURL
= SfxMedium::CreateTempCopyWithExt( pFileNameItem
->GetValue() );
2925 if ( !aNewTempFileURL
.isEmpty() )
2927 pImp
->m_pSet
->Put( SfxStringItem( SID_FILE_NAME
, aNewTempFileURL
) );
2928 pImp
->m_pSet
->ClearItem( SID_INPUTSTREAM
);
2929 pImp
->m_pSet
->ClearItem( SID_STREAM
);
2930 pImp
->m_pSet
->ClearItem( SID_CONTENT
);
2934 OSL_FAIL( "Can not create a new temporary file for crash recovery!\n" );
2939 SFX_ITEMSET_ARG( pImp
->m_pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, false );
2940 if ( pReadOnlyItem
&& pReadOnlyItem
->GetValue() )
2941 pImp
->m_bOriginallyReadOnly
= true;
2943 SFX_ITEMSET_ARG( pImp
->m_pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, false );
2944 if (!pFileNameItem
) throw uno::RuntimeException();
2945 pImp
->m_aLogicName
= pFileNameItem
->GetValue();
2946 pImp
->m_nStorOpenMode
= pImp
->m_bOriginallyReadOnly
? SFX_STREAM_READONLY
: SFX_STREAM_READWRITE
;
2951 //------------------------------------------------------------------
2953 SfxMedium::SfxMedium( const uno::Reference
< embed::XStorage
>& rStor
, const String
& rBaseURL
, const SfxItemSet
* p
) :
2954 pImp(new SfxMedium_Impl(this))
2956 OUString aType
= SfxFilter::GetTypeFromStorage(rStor
);
2957 pImp
->m_pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4EA( aType
);
2958 DBG_ASSERT( pImp
->m_pFilter
, "No Filter for storage found!" );
2961 pImp
->xStorage
= rStor
;
2962 pImp
->bDisposeStorage
= false;
2964 // always take BaseURL first, could be overwritten by ItemSet
2965 GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, rBaseURL
) );
2967 GetItemSet()->Put( *p
);
2970 //------------------------------------------------------------------
2972 SfxMedium::SfxMedium( const uno::Reference
< embed::XStorage
>& rStor
, const String
& rBaseURL
, const String
&rTypeName
, const SfxItemSet
* p
) :
2973 pImp(new SfxMedium_Impl(this))
2975 pImp
->m_pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4EA( rTypeName
);
2976 DBG_ASSERT( pImp
->m_pFilter
, "No Filter for storage found!" );
2979 pImp
->xStorage
= rStor
;
2980 pImp
->bDisposeStorage
= false;
2982 // always take BaseURL first, could be overwritten by ItemSet
2983 GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, rBaseURL
) );
2985 GetItemSet()->Put( *p
);
2988 //------------------------------------------------------------------
2990 SfxMedium::~SfxMedium()
2992 // if there is a requirement to clean the backup this is the last possibility to do it
2997 if( pImp
->bIsTemp
&& !pImp
->m_aName
.isEmpty() )
3000 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aTemp
))
3002 OSL_FAIL("Physical name not convertible!");
3005 if ( !::utl::UCBContentHelper::Kill( aTemp
) )
3007 OSL_FAIL("Couldn't remove temporary file!");
3014 const OUString
& SfxMedium::GetName() const
3016 return pImp
->m_aLogicName
;
3019 const INetURLObject
& SfxMedium::GetURLObject() const
3021 if (!pImp
->m_pURLObj
)
3023 pImp
->m_pURLObj
= new INetURLObject( pImp
->m_aLogicName
);
3024 if (pImp
->m_pURLObj
->HasMark())
3025 *pImp
->m_pURLObj
= INetURLObject( pImp
->m_aLogicName
).GetURLNoMark();
3028 return *pImp
->m_pURLObj
;
3031 void SfxMedium::SetExpired_Impl( const DateTime
& rDateTime
)
3033 pImp
->aExpireTime
= rDateTime
;
3035 //----------------------------------------------------------------
3037 sal_Bool
SfxMedium::IsExpired() const
3039 return pImp
->aExpireTime
.IsValidAndGregorian() && pImp
->aExpireTime
< DateTime( DateTime::SYSTEM
);
3041 //----------------------------------------------------------------
3043 void SfxMedium::ForceSynchronStream_Impl( sal_Bool bForce
)
3045 if( pImp
->m_pInStream
)
3047 SvLockBytes
* pBytes
= pImp
->m_pInStream
->GetLockBytes();
3049 pBytes
->SetSynchronMode( bForce
);
3053 //----------------------------------------------------------------
3054 SfxFrame
* SfxMedium::GetLoadTargetFrame() const
3056 return pImp
->wLoadTargetFrame
;
3059 void SfxMedium::setStreamToLoadFrom(const com::sun::star::uno::Reference
<com::sun::star::io::XInputStream
>& xInputStream
,sal_Bool bIsReadOnly
)
3061 pImp
->m_xInputStreamToLoadFrom
= xInputStream
;
3062 pImp
->m_bInputStreamIsReadOnly
= bIsReadOnly
;
3065 void SfxMedium::SetLoadTargetFrame(SfxFrame
* pFrame
)
3067 pImp
->wLoadTargetFrame
= pFrame
;
3069 //----------------------------------------------------------------
3071 void SfxMedium::SetStorage_Impl( const uno::Reference
< embed::XStorage
>& rStor
)
3073 pImp
->xStorage
= rStor
;
3075 //----------------------------------------------------------------
3077 SfxItemSet
* SfxMedium::GetItemSet() const
3079 // this method *must* return an ItemSet, returning NULL can cause crashes
3081 pImp
->m_pSet
= new SfxAllItemSet( SFX_APP()->GetPool() );
3082 return pImp
->m_pSet
;
3084 //----------------------------------------------------------------
3086 SvKeyValueIterator
* SfxMedium::GetHeaderAttributes_Impl()
3088 if( !pImp
->xAttributes
.Is() )
3090 pImp
->xAttributes
= SvKeyValueIteratorRef( new SvKeyValueIterator
);
3092 if ( GetContent().is() )
3096 Any aAny
= pImp
->aContent
.getPropertyValue( OUString("MediaType") );
3097 OUString aContentType
;
3098 aAny
>>= aContentType
;
3100 pImp
->xAttributes
->Append( SvKeyValue( OUString("content-type"), aContentType
) );
3102 catch ( const ::com::sun::star::uno::Exception
& )
3108 return pImp
->xAttributes
;
3111 ::com::sun::star::uno::Reference
< ::com::sun::star::io::XInputStream
> SfxMedium::GetInputStream()
3113 if ( !pImp
->xInputStream
.is() )
3115 return pImp
->xInputStream
;
3118 const uno::Sequence
< util::RevisionTag
>& SfxMedium::GetVersionList( bool _bNoReload
)
3120 // if the medium has no name, then this medium should represent a new document and can have no version info
3121 if ( ( !_bNoReload
|| !pImp
->m_bVersionsAlreadyLoaded
) && !pImp
->aVersions
.getLength() &&
3122 ( !pImp
->m_aName
.isEmpty() || !pImp
->m_aLogicName
.isEmpty() ) && GetStorage().is() )
3124 uno::Reference
< document::XDocumentRevisionListPersistence
> xReader
=
3125 document::DocumentRevisionListPersistence::create( comphelper::getProcessComponentContext() );
3128 pImp
->aVersions
= xReader
->load( GetStorage() );
3130 catch ( const uno::Exception
& )
3135 if ( !pImp
->m_bVersionsAlreadyLoaded
)
3136 pImp
->m_bVersionsAlreadyLoaded
= true;
3138 return pImp
->aVersions
;
3141 uno::Sequence
< util::RevisionTag
> SfxMedium::GetVersionList( const uno::Reference
< embed::XStorage
>& xStorage
)
3143 uno::Reference
< document::XDocumentRevisionListPersistence
> xReader
=
3144 document::DocumentRevisionListPersistence::create( comphelper::getProcessComponentContext() );
3147 return xReader
->load( xStorage
);
3149 catch ( const uno::Exception
& )
3153 return uno::Sequence
< util::RevisionTag
>();
3156 sal_uInt16
SfxMedium::AddVersion_Impl( util::RevisionTag
& rRevision
)
3158 if ( GetStorage().is() )
3160 // To determine a unique name for the stream
3161 std::vector
<sal_uInt32
> aLongs
;
3162 sal_Int32 nLength
= pImp
->aVersions
.getLength();
3163 for ( sal_Int32 m
=0; m
<nLength
; m
++ )
3165 sal_uInt32 nVer
= static_cast<sal_uInt32
>(String( pImp
->aVersions
[m
].Identifier
).Copy(7).ToInt32());
3167 for ( n
=0; n
<aLongs
.size(); ++n
)
3168 if ( nVer
<aLongs
[n
] )
3171 aLongs
.insert( aLongs
.begin()+n
, nVer
);
3175 for ( nKey
=0; nKey
<aLongs
.size(); ++nKey
)
3176 if ( aLongs
[nKey
] > ( sal_uIntPtr
) nKey
+1 )
3179 OUString aRevName
= "Version" + OUString::number( nKey
+ 1 );
3180 pImp
->aVersions
.realloc( nLength
+1 );
3181 rRevision
.Identifier
= aRevName
;
3182 pImp
->aVersions
[nLength
] = rRevision
;
3189 sal_Bool
SfxMedium::RemoveVersion_Impl( const OUString
& rName
)
3191 if ( !pImp
->aVersions
.getLength() )
3194 sal_Int32 nLength
= pImp
->aVersions
.getLength();
3195 for ( sal_Int32 n
=0; n
<nLength
; n
++ )
3197 if ( pImp
->aVersions
[n
].Identifier
== rName
)
3199 for ( sal_Int32 m
=n
; m
<nLength
-1; m
++ )
3200 pImp
->aVersions
[m
] = pImp
->aVersions
[m
+1];
3201 pImp
->aVersions
.realloc(nLength
-1);
3209 sal_Bool
SfxMedium::TransferVersionList_Impl( SfxMedium
& rMedium
)
3211 if ( rMedium
.pImp
->aVersions
.getLength() )
3213 pImp
->aVersions
= rMedium
.pImp
->aVersions
;
3220 sal_Bool
SfxMedium::SaveVersionList_Impl( sal_Bool
/*bUseXML*/ )
3222 if ( GetStorage().is() )
3224 if ( !pImp
->aVersions
.getLength() )
3227 uno::Reference
< document::XDocumentRevisionListPersistence
> xWriter
=
3228 document::DocumentRevisionListPersistence::create( comphelper::getProcessComponentContext() );
3231 xWriter
->store( GetStorage(), pImp
->aVersions
);
3234 catch ( const uno::Exception
& )
3242 //----------------------------------------------------------------
3243 sal_Bool
SfxMedium::IsReadOnly()
3245 // a) ReadOnly filter cant produce read/write contents!
3247 (pImp
->m_pFilter
) &&
3248 ((pImp
->m_pFilter
->GetFilterFlags() & SFX_FILTER_OPENREADONLY
) == SFX_FILTER_OPENREADONLY
)
3251 // b) if filter allow read/write contents .. check open mode of the storage
3253 bReadOnly
= !( GetOpenMode() & STREAM_WRITE
);
3255 // c) the API can force the readonly state!
3258 SFX_ITEMSET_ARG( GetItemSet(), pItem
, SfxBoolItem
, SID_DOC_READONLY
, false);
3260 bReadOnly
= pItem
->GetValue();
3266 bool SfxMedium::IsOriginallyReadOnly() const
3268 return pImp
->m_bOriginallyReadOnly
;
3271 //----------------------------------------------------------------
3272 sal_Bool
SfxMedium::SetWritableForUserOnly( const OUString
& aURL
)
3274 // UCB does not allow to allow write access only for the user,
3276 bool bResult
= false;
3278 ::osl::DirectoryItem aDirItem
;
3279 if ( ::osl::DirectoryItem::get( aURL
, aDirItem
) == ::osl::FileBase::E_None
)
3281 ::osl::FileStatus
aFileStatus( osl_FileStatus_Mask_Attributes
);
3282 if ( aDirItem
.getFileStatus( aFileStatus
) == osl::FileBase::E_None
3283 && aFileStatus
.isValid( osl_FileStatus_Mask_Attributes
) )
3285 sal_uInt64 nAttributes
= aFileStatus
.getAttributes();
3287 nAttributes
&= ~(osl_File_Attribute_OwnWrite
|
3288 osl_File_Attribute_GrpWrite
|
3289 osl_File_Attribute_OthWrite
|
3290 osl_File_Attribute_ReadOnly
);
3291 nAttributes
|= (osl_File_Attribute_OwnWrite
|
3292 osl_File_Attribute_OwnRead
);
3294 bResult
= ( osl::File::setAttributes( aURL
, nAttributes
) == ::osl::FileBase::E_None
);
3301 //----------------------------------------------------------------
3302 void SfxMedium::CreateTempFile( sal_Bool bReplace
)
3304 if ( pImp
->pTempFile
)
3309 DELETEZ( pImp
->pTempFile
);
3310 pImp
->m_aName
= OUString();
3313 pImp
->pTempFile
= new ::utl::TempFile();
3314 pImp
->pTempFile
->EnableKillingFile( true );
3315 pImp
->m_aName
= pImp
->pTempFile
->GetFileName();
3316 OUString aTmpURL
= pImp
->pTempFile
->GetURL();
3317 if ( pImp
->m_aName
.isEmpty() || aTmpURL
.isEmpty() )
3319 SetError( ERRCODE_IO_CANTWRITE
, OUString( OSL_LOG_PREFIX
) );
3323 if ( !(pImp
->m_nStorOpenMode
& STREAM_TRUNC
) )
3325 bool bTransferSuccess
= false;
3327 if ( GetContent().is()
3328 && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
3329 && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
3331 // if there is already such a document, we should copy it
3332 // if it is a file system use OS copy process
3335 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
3336 INetURLObject
aTmpURLObj( aTmpURL
);
3337 OUString aFileName
= aTmpURLObj
.getName( INetURLObject::LAST_SEGMENT
,
3339 INetURLObject::DECODE_WITH_CHARSET
);
3340 if ( !aFileName
.isEmpty() && aTmpURLObj
.removeSegment() )
3342 ::ucbhelper::Content
aTargetContent( aTmpURLObj
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
, comphelper::getProcessComponentContext() );
3343 OUString sMimeType
= pImp
->getFilterMimeType();
3344 if ( aTargetContent
.transferContent( pImp
->aContent
, ::ucbhelper::InsertOperation_COPY
, aFileName
, NameClash::OVERWRITE
, sMimeType
) )
3346 SetWritableForUserOnly( aTmpURL
);
3347 bTransferSuccess
= true;
3351 catch( const uno::Exception
& )
3354 if ( bTransferSuccess
)
3361 if ( !bTransferSuccess
&& pImp
->m_pInStream
)
3363 // the case when there is no URL-access available or this is a remote protocoll
3364 // but there is an input stream
3366 if ( pImp
->m_pOutStream
)
3368 char *pBuf
= new char [8192];
3369 sal_uInt32 nErr
= ERRCODE_NONE
;
3371 pImp
->m_pInStream
->Seek(0);
3372 pImp
->m_pOutStream
->Seek(0);
3374 while( !pImp
->m_pInStream
->IsEof() && nErr
== ERRCODE_NONE
)
3376 sal_uInt32 nRead
= pImp
->m_pInStream
->Read( pBuf
, 8192 );
3377 nErr
= pImp
->m_pInStream
->GetError();
3378 pImp
->m_pOutStream
->Write( pBuf
, nRead
);
3381 bTransferSuccess
= true;
3385 CloseOutStream_Impl();
3389 // Quite strange design, but currently it is expected that in this case no transfer happens
3390 // TODO/LATER: get rid of this inconsistent part of the call design
3391 bTransferSuccess
= true;
3395 if ( !bTransferSuccess
)
3397 SetError( ERRCODE_IO_CANTWRITE
, OUString( OSL_LOG_PREFIX
) );
3405 //----------------------------------------------------------------
3406 void SfxMedium::CreateTempFileNoCopy()
3408 // this call always replaces the existing temporary file
3409 if ( pImp
->pTempFile
)
3410 delete pImp
->pTempFile
;
3412 pImp
->pTempFile
= new ::utl::TempFile();
3413 pImp
->pTempFile
->EnableKillingFile( true );
3414 pImp
->m_aName
= pImp
->pTempFile
->GetFileName();
3415 if ( pImp
->m_aName
.isEmpty() )
3417 SetError( ERRCODE_IO_CANTWRITE
, OUString( OSL_LOG_PREFIX
) );
3421 CloseOutStream_Impl();
3425 sal_Bool
SfxMedium::SignContents_Impl( sal_Bool bScriptingContent
, const OUString
& aODFVersion
, sal_Bool bHasValidDocumentSignature
)
3427 bool bChanges
= false;
3429 // the medium should be closed to be able to sign, the caller is responsible to close it
3430 if ( !IsOpen() && !GetError() )
3432 // The component should know if there was a valid document signature, since
3433 // it should show a warning in this case
3434 uno::Reference
< security::XDocumentDigitalSignatures
> xSigner(
3435 security::DocumentDigitalSignatures::createWithVersionAndValidSignature(
3436 comphelper::getProcessComponentContext(), aODFVersion
, bHasValidDocumentSignature
) );
3438 uno::Reference
< embed::XStorage
> xWriteableZipStor
;
3439 if ( !IsReadOnly() )
3441 // we can reuse the temporary file if there is one already
3442 CreateTempFile( false );
3447 if ( !pImp
->xStream
.is() )
3448 throw uno::RuntimeException();
3450 xWriteableZipStor
= ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xStream
);
3451 if ( !xWriteableZipStor
.is() )
3452 throw uno::RuntimeException();
3454 uno::Reference
< embed::XStorage
> xMetaInf
= xWriteableZipStor
->openStorageElement(
3455 OUString( "META-INF" ),
3456 embed::ElementModes::READWRITE
);
3457 if ( !xMetaInf
.is() )
3458 throw uno::RuntimeException();
3460 if ( bScriptingContent
)
3462 // If the signature has already the document signature it will be removed
3463 // after the scripting signature is inserted.
3464 uno::Reference
< io::XStream
> xStream(
3465 xMetaInf
->openStreamElement( xSigner
->getScriptingContentSignatureDefaultStreamName(),
3466 embed::ElementModes::READWRITE
),
3467 uno::UNO_SET_THROW
);
3469 if ( xSigner
->signScriptingContent( GetZipStorageToSign_Impl(), xStream
) )
3471 // remove the document signature if any
3472 OUString aDocSigName
= xSigner
->getDocumentContentSignatureDefaultStreamName();
3473 if ( !aDocSigName
.isEmpty() && xMetaInf
->hasByName( aDocSigName
) )
3474 xMetaInf
->removeElement( aDocSigName
);
3476 uno::Reference
< embed::XTransactedObject
> xTransact( xMetaInf
, uno::UNO_QUERY_THROW
);
3477 xTransact
->commit();
3478 xTransact
.set( xWriteableZipStor
, uno::UNO_QUERY_THROW
);
3479 xTransact
->commit();
3481 // the temporary file has been written, commit it to the original file
3488 uno::Reference
< io::XStream
> xStream(
3489 xMetaInf
->openStreamElement( xSigner
->getDocumentContentSignatureDefaultStreamName(),
3490 embed::ElementModes::READWRITE
),
3491 uno::UNO_SET_THROW
);
3493 if ( xSigner
->signDocumentContent( GetZipStorageToSign_Impl(), xStream
) )
3495 uno::Reference
< embed::XTransactedObject
> xTransact( xMetaInf
, uno::UNO_QUERY_THROW
);
3496 xTransact
->commit();
3497 xTransact
.set( xWriteableZipStor
, uno::UNO_QUERY_THROW
);
3498 xTransact
->commit();
3500 // the temporary file has been written, commit it to the original file
3506 catch ( const uno::Exception
& )
3508 OSL_FAIL( "Couldn't use signing functionality!\n" );
3517 if ( bScriptingContent
)
3518 xSigner
->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference
< io::XInputStream
>() );
3520 xSigner
->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference
< io::XInputStream
>() );
3522 catch( const uno::Exception
& )
3524 OSL_FAIL( "Couldn't use signing functionality!\n" );
3534 //----------------------------------------------------------------
3535 sal_uInt16
SfxMedium::GetCachedSignatureState_Impl()
3537 return pImp
->m_nSignatureState
;
3540 //----------------------------------------------------------------
3541 void SfxMedium::SetCachedSignatureState_Impl( sal_uInt16 nState
)
3543 pImp
->m_nSignatureState
= nState
;
3546 sal_Bool
SfxMedium::HasStorage_Impl() const
3548 return pImp
->xStorage
.is();
3551 sal_Bool
SfxMedium::IsOpen() const
3553 return pImp
->m_pInStream
|| pImp
->m_pOutStream
|| pImp
->xStorage
.is();
3556 OUString
SfxMedium::CreateTempCopyWithExt( const OUString
& aURL
)
3560 if ( !aURL
.isEmpty() )
3562 sal_Int32 nPrefixLen
= aURL
.lastIndexOf( '.' );
3563 String aExt
= ( nPrefixLen
== -1 ) ? String() : String( aURL
.copy( nPrefixLen
) );
3565 OUString aNewTempFileURL
= ::utl::TempFile( String(), &aExt
).GetURL();
3566 if ( !aNewTempFileURL
.isEmpty() )
3568 INetURLObject
aSource( aURL
);
3569 INetURLObject
aDest( aNewTempFileURL
);
3570 OUString aFileName
= aDest
.getName( INetURLObject::LAST_SEGMENT
,
3572 INetURLObject::DECODE_WITH_CHARSET
);
3573 if ( !aFileName
.isEmpty() && aDest
.removeSegment() )
3577 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
3578 ::ucbhelper::Content
aTargetContent( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
, comphelper::getProcessComponentContext() );
3579 ::ucbhelper::Content
aSourceContent( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
, comphelper::getProcessComponentContext() );
3580 if ( aTargetContent
.transferContent( aSourceContent
,
3581 ::ucbhelper::InsertOperation_COPY
,
3583 NameClash::OVERWRITE
) )
3586 aResult
= aNewTempFileURL
;
3589 catch( const uno::Exception
& )
3598 sal_Bool
SfxMedium::CallApproveHandler( const uno::Reference
< task::XInteractionHandler
>& xHandler
, uno::Any aRequest
, sal_Bool bAllowAbort
)
3600 bool bResult
= false;
3602 if ( xHandler
.is() )
3606 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( bAllowAbort
? 2 : 1 );
3608 ::rtl::Reference
< ::comphelper::OInteractionApprove
> pApprove( new ::comphelper::OInteractionApprove
);
3609 aContinuations
[ 0 ] = pApprove
.get();
3613 ::rtl::Reference
< ::comphelper::OInteractionAbort
> pAbort( new ::comphelper::OInteractionAbort
);
3614 aContinuations
[ 1 ] = pAbort
.get();
3617 xHandler
->handle(::framework::InteractionRequest::CreateRequest (aRequest
,aContinuations
));
3618 bResult
= pApprove
->wasSelected();
3620 catch( const Exception
& )
3628 OUString
SfxMedium::SwitchDocumentToTempFile()
3630 // the method returns empty string in case of failure
3632 OUString aOrigURL
= pImp
->m_aLogicName
;
3634 if ( !aOrigURL
.isEmpty() )
3636 sal_Int32 nPrefixLen
= aOrigURL
.lastIndexOf( '.' );
3637 String aExt
= ( nPrefixLen
== -1 ) ? String() : String( aOrigURL
.copy( nPrefixLen
) );
3638 OUString aNewURL
= ::utl::TempFile( String(), &aExt
).GetURL();
3640 // TODO/LATER: In future the aLogicName should be set to shared folder URL
3641 // and a temporary file should be created. Transport_Impl should be impossible then.
3642 if ( !aNewURL
.isEmpty() )
3644 uno::Reference
< embed::XStorage
> xStorage
= GetStorage();
3645 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY
);
3647 if ( xOptStorage
.is() )
3649 // TODO/LATER: reuse the pImp->pTempFile if it already exists
3650 CanDisposeStorage_Impl( false );
3652 SetPhysicalName_Impl( String() );
3655 // remove the readonly state
3656 bool bWasReadonly
= false;
3657 pImp
->m_nStorOpenMode
= SFX_STREAM_READWRITE
;
3658 SFX_ITEMSET_ARG( pImp
->m_pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, false );
3659 if ( pReadOnlyItem
&& pReadOnlyItem
->GetValue() )
3660 bWasReadonly
= true;
3661 GetItemSet()->ClearItem( SID_DOC_READONLY
);
3664 LockOrigFileOnDemand( false, false );
3665 CreateTempFile( true );
3668 if ( pImp
->xStream
.is() )
3672 xOptStorage
->writeAndAttachToStream( pImp
->xStream
);
3673 pImp
->xStorage
= xStorage
;
3676 catch( const uno::Exception
& )
3680 if ( aResult
.isEmpty() )
3683 SetPhysicalName_Impl( String() );
3684 SetName( aOrigURL
);
3687 // set the readonly state back
3688 pImp
->m_nStorOpenMode
= SFX_STREAM_READONLY
;
3689 GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY
, true));
3692 pImp
->xStorage
= xStorage
;
3701 sal_Bool
SfxMedium::SwitchDocumentToFile( const OUString
& aURL
)
3703 // the method is only for storage based documents
3704 bool bResult
= false;
3705 OUString aOrigURL
= pImp
->m_aLogicName
;
3707 if ( !aURL
.isEmpty() && !aOrigURL
.isEmpty() )
3709 uno::Reference
< embed::XStorage
> xStorage
= GetStorage();
3710 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY
);
3712 if ( xOptStorage
.is() )
3714 // TODO/LATER: reuse the pImp->pTempFile if it already exists
3715 CanDisposeStorage_Impl( false );
3717 SetPhysicalName_Impl( String() );
3720 // open the temporary file based document
3722 LockOrigFileOnDemand( false, false );
3723 CreateTempFile( true );
3726 if ( pImp
->xStream
.is() )
3730 uno::Reference
< io::XTruncate
> xTruncate( pImp
->xStream
, uno::UNO_QUERY_THROW
);
3731 if ( xTruncate
.is() )
3732 xTruncate
->truncate();
3734 xOptStorage
->writeAndAttachToStream( pImp
->xStream
);
3735 pImp
->xStorage
= xStorage
;
3738 catch( const uno::Exception
& )
3745 SetPhysicalName_Impl( String() );
3746 SetName( aOrigURL
);
3748 pImp
->xStorage
= xStorage
;
3756 void SfxMedium::SetInCheckIn( bool bInCheckIn
)
3758 pImp
->m_bInCheckIn
= bInCheckIn
;
3761 bool SfxMedium::IsInCheckIn( )
3763 return pImp
->m_bInCheckIn
;
3766 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */