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 #if HAVE_FEATURE_MACOSX_SANDBOX
149 // check whether system file locking has been used, the default value is false
150 bool bUseSystemLock
= false;
154 uno::Reference
< uno::XInterface
> xCommonConfig
= ::comphelper::ConfigurationHelper::openConfig(
155 ::comphelper::getProcessComponentContext(),
156 OUString( "/org.openoffice.Office.Common" ),
157 ::comphelper::ConfigurationHelper::E_STANDARD
);
158 if ( !xCommonConfig
.is() )
159 throw uno::RuntimeException();
161 ::comphelper::ConfigurationHelper::readRelativeKey(
164 OUString( "UseDocumentSystemFileLocking" ) ) >>= bUseSystemLock
;
166 catch( const uno::Exception
& )
170 return bUseSystemLock
;
174 //----------------------------------------------------------------
175 bool IsOOoLockFileUsed()
177 #if HAVE_FEATURE_MACOSX_SANDBOX
180 // check whether system file locking has been used, the default value is false
181 bool bOOoLockFileUsed
= false;
185 uno::Reference
< uno::XInterface
> xCommonConfig
= ::comphelper::ConfigurationHelper::openConfig(
186 ::comphelper::getProcessComponentContext(),
187 OUString( "/org.openoffice.Office.Common" ),
188 ::comphelper::ConfigurationHelper::E_STANDARD
);
189 if ( !xCommonConfig
.is() )
190 throw uno::RuntimeException();
192 ::comphelper::ConfigurationHelper::readRelativeKey(
195 OUString( "UseDocumentOOoLockFile" ) ) >>= bOOoLockFileUsed
;
197 catch( const uno::Exception
& )
201 return bOOoLockFileUsed
;
207 return officecfg::Office::Common::Misc::UseLocking::get();
212 } // anonymous namespace
213 //==========================================================
216 //----------------------------------------------------------------
217 class SfxMediumHandler_Impl
: public ::cppu::WeakImplHelper1
< com::sun::star::task::XInteractionHandler
>
219 com::sun::star::uno::Reference
< com::sun::star::task::XInteractionHandler
> m_xInter
;
222 virtual void SAL_CALL
handle( const com::sun::star::uno::Reference
< com::sun::star::task::XInteractionRequest
>& xRequest
)
223 throw( com::sun::star::uno::RuntimeException
);
225 SfxMediumHandler_Impl( com::sun::star::uno::Reference
< com::sun::star::task::XInteractionHandler
> xInteraction
)
226 : m_xInter( xInteraction
)
229 ~SfxMediumHandler_Impl();
232 //----------------------------------------------------------------
233 SfxMediumHandler_Impl::~SfxMediumHandler_Impl()
237 //----------------------------------------------------------------
238 void SAL_CALL
SfxMediumHandler_Impl::handle( const com::sun::star::uno::Reference
< com::sun::star::task::XInteractionRequest
>& xRequest
)
239 throw( com::sun::star::uno::RuntimeException
)
244 com::sun::star::uno::Any aRequest
= xRequest
->getRequest();
245 com::sun::star::ucb::InteractiveIOException aIoException
;
246 com::sun::star::ucb::UnsupportedDataSinkException aSinkException
;
247 if ( (aRequest
>>= aIoException
) && ( aIoException
.Code
== IOErrorCode_ACCESS_DENIED
|| aIoException
.Code
== IOErrorCode_LOCKING_VIOLATION
) )
250 if ( aRequest
>>= aSinkException
)
253 m_xInter
->handle( xRequest
);
256 class SfxMedium_Impl
: boost::noncopyable
259 StreamMode m_nStorOpenMode
;
262 ::ucbhelper::Content aContent
;
263 bool bUpdatePickList
:1;
265 bool bDownloadDone
:1;
267 bool bUseInteractionHandler
:1;
268 bool bAllowDefaultIntHdl
:1;
269 bool bDisposeStorage
:1;
270 bool bStorageBasedOnInStream
:1;
271 bool m_bSalvageMode
:1;
272 bool m_bVersionsAlreadyLoaded
:1;
274 bool m_bGotDateTime
:1;
275 bool m_bRemoveBackup
:1;
276 bool m_bOriginallyReadOnly
:1;
277 bool m_bTriedStorage
:1;
279 bool m_bInputStreamIsReadOnly
:1;
283 OUString m_aLogicName
;
284 OUString m_aLongName
;
286 mutable SfxItemSet
* m_pSet
;
287 mutable INetURLObject
* m_pURLObj
;
289 const SfxFilter
* m_pFilter
;
290 boost::scoped_ptr
<SfxFilter
> m_pCustomFilter
;
292 SfxMedium
* pAntiImpl
;
293 SvStream
* m_pInStream
;
294 SvStream
* m_pOutStream
;
296 const SfxFilter
* pOrigFilter
;
298 DateTime aExpireTime
;
299 SfxFrameWeak wLoadTargetFrame
;
300 SvKeyValueIteratorRef xAttributes
;
302 svtools::AsynchronLink aDoneLink
;
304 uno::Sequence
< util::RevisionTag
> aVersions
;
306 ::utl::TempFile
* pTempFile
;
308 uno::Reference
<embed::XStorage
> xStorage
;
309 uno::Reference
<embed::XStorage
> m_xZipStorage
;
310 uno::Reference
<io::XInputStream
> m_xInputStreamToLoadFrom
;
311 uno::Reference
<io::XInputStream
> xInputStream
;
312 uno::Reference
<io::XStream
> xStream
;
313 uno::Reference
<io::XStream
> m_xLockingStream
;
314 uno::Reference
<task::XInteractionHandler
> xInteraction
;
315 uno::Reference
<logging::XSimpleLogRing
> m_xLogRing
;
317 sal_uInt32 nLastStorageError
;
319 OUString m_aBackupURL
;
321 // the following member is changed and makes sense only during saving
322 // TODO/LATER: in future the signature state should be controlled by the medium not by the document
323 // in this case the member will hold this information
324 sal_uInt16 m_nSignatureState
;
326 util::DateTime m_aDateTime
;
328 SfxMedium_Impl( SfxMedium
* pAntiImplP
);
331 OUString
getFilterMimeType()
332 { return m_pFilter
== 0 ? OUString() : m_pFilter
->GetMimeType(); }
335 //------------------------------------------------------------------
336 SfxMedium_Impl::SfxMedium_Impl( SfxMedium
* pAntiImplP
) :
337 m_nStorOpenMode(SFX_STREAM_READWRITE
),
338 m_eError(SVSTREAM_OK
),
339 bUpdatePickList(true),
341 bDownloadDone( true ),
343 bUseInteractionHandler( true ),
344 bAllowDefaultIntHdl( false ),
345 bDisposeStorage( false ),
346 bStorageBasedOnInStream( false ),
347 m_bSalvageMode( false ),
348 m_bVersionsAlreadyLoaded( false ),
350 m_bGotDateTime( false ),
351 m_bRemoveBackup( false ),
352 m_bOriginallyReadOnly(false),
353 m_bTriedStorage(false),
355 m_bInputStreamIsReadOnly(false),
360 pAntiImpl( pAntiImplP
),
364 aExpireTime( Date( Date::SYSTEM
) + 10, Time( Time::SYSTEM
) ),
366 nLastStorageError( 0 ),
367 m_nSignatureState( SIGNATURESTATE_NOSIGNATURES
)
369 aDoneLink
.CreateMutex();
372 //------------------------------------------------------------------
373 SfxMedium_Impl::~SfxMedium_Impl()
375 aDoneLink
.ClearPendingCall();
382 void SfxMedium::ResetError()
384 pImp
->m_eError
= SVSTREAM_OK
;
385 if( pImp
->m_pInStream
)
386 pImp
->m_pInStream
->ResetError();
387 if( pImp
->m_pOutStream
)
388 pImp
->m_pOutStream
->ResetError();
391 //------------------------------------------------------------------
392 sal_uInt32
SfxMedium::GetLastStorageCreationState()
394 return pImp
->nLastStorageError
;
397 //------------------------------------------------------------------
398 void SfxMedium::AddLog( const OUString
& aMessage
)
400 if ( !pImp
->m_xLogRing
.is() )
404 Reference
<XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
405 pImp
->m_xLogRing
.set( logging::DocumentIOLogRing::get(xContext
) );
407 catch( const uno::Exception
& )
411 if ( pImp
->m_xLogRing
.is() )
412 pImp
->m_xLogRing
->logString( aMessage
);
415 //------------------------------------------------------------------
416 void SfxMedium::SetError( sal_uInt32 nError
, const OUString
& aLogMessage
)
418 pImp
->m_eError
= nError
;
419 if ( pImp
->m_eError
!= ERRCODE_NONE
&& !aLogMessage
.isEmpty() )
420 AddLog( aLogMessage
);
423 //------------------------------------------------------------------
424 sal_uInt32
SfxMedium::GetErrorCode() const
426 sal_uInt32 lError
= pImp
->m_eError
;
427 if(!lError
&& pImp
->m_pInStream
)
428 lError
= pImp
->m_pInStream
->GetErrorCode();
429 if(!lError
&& pImp
->m_pOutStream
)
430 lError
= pImp
->m_pOutStream
->GetErrorCode();
434 //------------------------------------------------------------------
435 void SfxMedium::CheckFileDate( const util::DateTime
& aInitDate
)
437 GetInitFileDate( true );
438 if ( pImp
->m_aDateTime
.Seconds
!= aInitDate
.Seconds
439 || pImp
->m_aDateTime
.Minutes
!= aInitDate
.Minutes
440 || pImp
->m_aDateTime
.Hours
!= aInitDate
.Hours
441 || pImp
->m_aDateTime
.Day
!= aInitDate
.Day
442 || pImp
->m_aDateTime
.Month
!= aInitDate
.Month
443 || pImp
->m_aDateTime
.Year
!= aInitDate
.Year
)
445 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
451 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
452 document::ChangedByOthersRequest() ) );
453 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 3 );
454 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl
.get() );
455 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl
.get() );
456 xInteractionRequestImpl
->setContinuations( aContinuations
);
458 xHandler
->handle( xInteractionRequestImpl
.get() );
460 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xInteractionRequestImpl
->getSelection();
461 if ( uno::Reference
< task::XInteractionAbort
>( xSelected
.get(), uno::UNO_QUERY
).is() )
463 SetError( ERRCODE_ABORT
, OUString( OSL_LOG_PREFIX
) );
466 catch ( const uno::Exception
& )
472 //------------------------------------------------------------------
473 sal_Bool
SfxMedium::DocNeedsFileDateCheck()
475 return ( !IsReadOnly() && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) );
478 //------------------------------------------------------------------
479 util::DateTime
SfxMedium::GetInitFileDate( sal_Bool bIgnoreOldValue
)
481 if ( ( bIgnoreOldValue
|| !pImp
->m_bGotDateTime
) && !pImp
->m_aLogicName
.isEmpty() )
485 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
486 ::ucbhelper::Content
aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, comphelper::getProcessComponentContext() );
488 aContent
.getPropertyValue( OUString("DateModified" ) ) >>= pImp
->m_aDateTime
;
489 pImp
->m_bGotDateTime
= true;
491 catch ( const ::com::sun::star::uno::Exception
& )
496 return pImp
->m_aDateTime
;
499 //------------------------------------------------------------------
500 Reference
< XContent
> SfxMedium::GetContent() const
502 if ( !pImp
->aContent
.get().is() )
504 Reference
< ::com::sun::star::ucb::XContent
> xContent
;
505 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
507 SFX_ITEMSET_ARG( pImp
->m_pSet
, pItem
, SfxUnoAnyItem
, SID_CONTENT
, false);
509 pItem
->GetValue() >>= xContent
;
515 pImp
->aContent
= ::ucbhelper::Content( xContent
, xEnv
, comphelper::getProcessComponentContext() );
517 catch ( const Exception
& )
523 // TODO: OSL_FAIL("SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
525 if ( !pImp
->m_aName
.isEmpty() )
526 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aURL
);
527 else if ( !pImp
->m_aLogicName
.isEmpty() )
528 aURL
= GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
529 if (!aURL
.isEmpty() )
530 ::ucbhelper::Content::create( aURL
, xEnv
, comphelper::getProcessComponentContext(), pImp
->aContent
);
534 return pImp
->aContent
.get();
537 //------------------------------------------------------------------
538 OUString
SfxMedium::GetBaseURL( bool bForSaving
)
541 const SfxStringItem
* pBaseURLItem
= static_cast<const SfxStringItem
*>( GetItemSet()->GetItem(SID_DOC_BASEURL
) );
543 aBaseURL
= pBaseURLItem
->GetValue();
544 else if ( GetContent().is() )
548 Any aAny
= pImp
->aContent
.getPropertyValue( OUString("BaseURI" ) );
551 catch ( const ::com::sun::star::uno::Exception
& )
555 if ( aBaseURL
.isEmpty() )
556 aBaseURL
= GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
562 bool bIsRemote
= IsRemote();
563 if( (bIsRemote
&& !aOpt
.IsSaveRelINet()) || (!pImp
->m_bRemote
&& !aOpt
.IsSaveRelFSys()) )
570 //------------------------------------------------------------------
571 SvStream
* SfxMedium::GetInStream()
573 if ( pImp
->m_pInStream
)
574 return pImp
->m_pInStream
;
576 if ( pImp
->pTempFile
)
578 pImp
->m_pInStream
= new SvFileStream(pImp
->m_aName
, pImp
->m_nStorOpenMode
);
580 pImp
->m_eError
= pImp
->m_pInStream
->GetError();
582 if (!pImp
->m_eError
&& (pImp
->m_nStorOpenMode
& STREAM_WRITE
)
583 && ! pImp
->m_pInStream
->IsWritable() )
585 pImp
->m_eError
= ERRCODE_IO_ACCESSDENIED
;
586 delete pImp
->m_pInStream
;
587 pImp
->m_pInStream
= NULL
;
590 return pImp
->m_pInStream
;
598 return pImp
->m_pInStream
;
601 //------------------------------------------------------------------
602 void SfxMedium::CloseInStream()
604 CloseInStream_Impl();
607 void SfxMedium::CloseInStream_Impl()
609 // if there is a storage based on the InStream, we have to
610 // close the storage, too, because otherwise the storage
611 // would use an invalid ( deleted ) stream.
612 if ( pImp
->m_pInStream
&& pImp
->xStorage
.is() )
614 if ( pImp
->bStorageBasedOnInStream
)
618 if ( pImp
->m_pInStream
&& !GetContent().is() )
620 CreateTempFile( true );
624 DELETEZ( pImp
->m_pInStream
);
626 pImp
->m_pSet
->ClearItem( SID_INPUTSTREAM
);
628 CloseZipStorage_Impl();
629 pImp
->xInputStream
.clear();
631 if ( !pImp
->m_pOutStream
)
633 // output part of the stream is not used so the whole stream can be closed
634 // TODO/LATER: is it correct?
635 pImp
->xStream
.clear();
637 pImp
->m_pSet
->ClearItem( SID_STREAM
);
641 //------------------------------------------------------------------
642 SvStream
* SfxMedium::GetOutStream()
644 if ( !pImp
->m_pOutStream
)
646 // Create a temp. file if there is none because we always
648 CreateTempFile( false );
650 if ( pImp
->pTempFile
)
652 // On windows we try to re-use XOutStream from xStream if that exists;
653 // because opening new SvFileStream in this situation may fail with ERROR_SHARING_VIOLATION
655 if (pImp
->xStream
.is())
657 assert(pImp
->xStream
->getOutputStream().is()); // need that...
658 pImp
->m_pOutStream
= utl::UcbStreamHelper::CreateStream(
659 pImp
->xStream
, false);
663 pImp
->m_pOutStream
= new SvFileStream(
664 pImp
->m_aName
, STREAM_STD_READWRITE
);
666 // On Unix don't try to re-use XOutStream from xStream if that exists;
667 // it causes fdo#59022 (fails opening files via SMB on Linux)
669 pImp
->m_pOutStream
= new SvFileStream(
670 pImp
->m_aName
, STREAM_STD_READWRITE
);
676 return pImp
->m_pOutStream
;
679 //------------------------------------------------------------------
680 sal_Bool
SfxMedium::CloseOutStream()
682 CloseOutStream_Impl();
686 sal_Bool
SfxMedium::CloseOutStream_Impl()
688 if ( pImp
->m_pOutStream
)
690 // if there is a storage based on the OutStream, we have to
691 // close the storage, too, because otherwise the storage
692 // would use an invalid ( deleted ) stream.
693 //TODO/MBA: how to deal with this?!
694 //maybe we need a new flag when the storage was created from the outstream
695 if ( pImp
->xStorage
.is() )
700 delete pImp
->m_pOutStream
;
701 pImp
->m_pOutStream
= NULL
;
704 if ( !pImp
->m_pInStream
)
706 // input part of the stream is not used so the whole stream can be closed
707 // TODO/LATER: is it correct?
708 pImp
->xStream
.clear();
710 pImp
->m_pSet
->ClearItem( SID_STREAM
);
716 //------------------------------------------------------------------
717 const OUString
& SfxMedium::GetPhysicalName() const
719 if ( pImp
->m_aName
.isEmpty() && !pImp
->m_aLogicName
.isEmpty() )
720 (( SfxMedium
*)this)->CreateFileStream();
722 // return the name then
723 return pImp
->m_aName
;
726 //------------------------------------------------------------------
727 void SfxMedium::CreateFileStream()
729 ForceSynchronStream_Impl( true );
731 if( pImp
->m_pInStream
)
733 CreateTempFile( false );
734 pImp
->bIsTemp
= true;
735 CloseInStream_Impl();
739 //------------------------------------------------------------------
740 sal_Bool
SfxMedium::Commit()
742 if( pImp
->xStorage
.is() )
743 StorageCommit_Impl();
744 else if( pImp
->m_pOutStream
)
745 pImp
->m_pOutStream
->Flush();
746 else if( pImp
->m_pInStream
)
747 pImp
->m_pInStream
->Flush();
749 if ( GetError() == SVSTREAM_OK
)
751 // does something only in case there is a temporary file ( means aName points to different location than aLogicName )
755 bool bResult
= ( GetError() == SVSTREAM_OK
);
757 if ( bResult
&& DocNeedsFileDateCheck() )
758 GetInitFileDate( true );
760 // remove truncation mode from the flags
761 pImp
->m_nStorOpenMode
&= (~STREAM_TRUNC
);
765 //------------------------------------------------------------------
766 sal_Bool
SfxMedium::IsStorage()
768 if ( pImp
->xStorage
.is() )
771 if ( pImp
->m_bTriedStorage
)
772 return pImp
->bIsStorage
;
774 if ( pImp
->pTempFile
)
777 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aURL
) )
779 OSL_FAIL("Physical name not convertible!");
781 pImp
->bIsStorage
= SotStorage::IsStorageFile( aURL
) && !SotStorage::IsOLEStorage( aURL
);
782 if ( !pImp
->bIsStorage
)
783 pImp
->m_bTriedStorage
= true;
785 else if ( GetInStream() )
787 pImp
->bIsStorage
= SotStorage::IsStorageFile( pImp
->m_pInStream
) && !SotStorage::IsOLEStorage( pImp
->m_pInStream
);
788 if ( !pImp
->m_pInStream
->GetError() && !pImp
->bIsStorage
)
789 pImp
->m_bTriedStorage
= true;
792 return pImp
->bIsStorage
;
795 //------------------------------------------------------------------
796 sal_Bool
SfxMedium::IsPreview_Impl()
798 bool bPreview
= false;
799 SFX_ITEMSET_ARG( GetItemSet(), pPreview
, SfxBoolItem
, SID_PREVIEW
, false);
801 bPreview
= pPreview
->GetValue();
804 SFX_ITEMSET_ARG( GetItemSet(), pFlags
, SfxStringItem
, SID_OPTIONS
, false);
807 String aFileFlags
= pFlags
->GetValue();
808 aFileFlags
.ToUpperAscii();
809 if ( STRING_NOTFOUND
!= aFileFlags
.Search( 'B' ) )
817 //------------------------------------------------------------------
818 void SfxMedium::StorageBackup_Impl()
820 ::ucbhelper::Content aOriginalContent
;
821 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
823 bool bBasedOnOriginalFile
= ( !pImp
->pTempFile
&& !( !pImp
->m_aLogicName
.isEmpty() && pImp
->m_bSalvageMode
)
824 && !GetURLObject().GetMainURL( INetURLObject::NO_DECODE
).isEmpty()
825 && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
826 && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) );
828 if ( bBasedOnOriginalFile
&& pImp
->m_aBackupURL
.isEmpty()
829 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, comphelper::getProcessComponentContext(), aOriginalContent
) )
831 DoInternalBackup_Impl( aOriginalContent
);
832 if( pImp
->m_aBackupURL
.isEmpty() )
833 SetError( ERRCODE_SFX_CANTCREATEBACKUP
, OUString( OSL_LOG_PREFIX
) );
837 //------------------------------------------------------------------
838 OUString
SfxMedium::GetBackup_Impl()
840 if ( pImp
->m_aBackupURL
.isEmpty() )
841 StorageBackup_Impl();
843 return pImp
->m_aBackupURL
;
846 //------------------------------------------------------------------
847 uno::Reference
< embed::XStorage
> SfxMedium::GetOutputStorage()
850 return uno::Reference
< embed::XStorage
>();
852 // if the medium was constructed with a Storage: use this one, not a temp. storage
853 // if a temporary storage already exists: use it
854 if ( pImp
->xStorage
.is() && ( pImp
->m_aLogicName
.isEmpty() || pImp
->pTempFile
) )
855 return pImp
->xStorage
;
857 // if necessary close stream that was used for reading
858 if ( pImp
->m_pInStream
&& !pImp
->m_pInStream
->IsWritable() )
861 DBG_ASSERT( !pImp
->m_pOutStream
, "OutStream in a readonly Medium?!" );
863 // TODO/LATER: The current solution is to store the document temporary and then copy it to the target location;
864 // in future it should be stored directly and then copied to the temporary location, since in this case no
865 // file attributes have to be preserved and system copying mechanics could be used instead of streaming.
866 CreateTempFileNoCopy();
871 //------------------------------------------------------------------
872 void SfxMedium::SetEncryptionDataToStorage_Impl()
874 // in case media-descriptor contains password it should be used on opening
875 if ( pImp
->xStorage
.is() && pImp
->m_pSet
)
877 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
878 if ( GetEncryptionData_Impl( pImp
->m_pSet
, aEncryptionData
) )
880 // replace the password with encryption data
881 pImp
->m_pSet
->ClearItem( SID_PASSWORD
);
882 pImp
->m_pSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
886 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( pImp
->xStorage
, aEncryptionData
);
888 catch( const uno::Exception
& )
890 OSL_FAIL( "It must be possible to set a common password for the storage" );
891 // TODO/LATER: set the error code in case of problem
892 // SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
898 //------------------------------------------------------------------
899 sal_Int8
SfxMedium::ShowLockedDocumentDialog( const uno::Sequence
< OUString
>& aData
, sal_Bool bIsLoading
, sal_Bool bOwnLock
)
901 sal_Int8 nResult
= LOCK_UI_NOLOCK
;
903 // show the interaction regarding the document opening
904 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
906 if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler
.is() && ( bIsLoading
|| bOwnLock
) )
908 OUString aDocumentURL
= GetURLObject().GetLastName();
910 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xInteractionRequestImpl
;
914 if ( aData
.getLength() > LOCKFILE_EDITTIME_ID
)
915 aInfo
= aData
[LOCKFILE_EDITTIME_ID
];
917 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
918 document::OwnLockOnDocumentRequest( OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
, !bIsLoading
) ) );
922 if ( aData
.getLength() > LOCKFILE_EDITTIME_ID
)
924 if ( !aData
[LOCKFILE_OOOUSERNAME_ID
].isEmpty() )
925 aInfo
= aData
[LOCKFILE_OOOUSERNAME_ID
];
927 aInfo
= aData
[LOCKFILE_SYSUSERNAME_ID
];
929 if ( !aInfo
.isEmpty() && !aData
[LOCKFILE_EDITTIME_ID
].isEmpty() )
931 aInfo
+= OUString( " ( " );
932 aInfo
+= aData
[LOCKFILE_EDITTIME_ID
];
933 aInfo
+= OUString( " )" );
939 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
940 document::LockedDocumentRequest( OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
) ) );
944 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
945 document::LockedOnSavingRequest( OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
) ) );
950 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 3 );
951 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl
.get() );
952 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl
.get() );
953 aContinuations
[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl
.get() );
954 xInteractionRequestImpl
->setContinuations( aContinuations
);
956 xHandler
->handle( xInteractionRequestImpl
.get() );
958 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xInteractionRequestImpl
->getSelection();
959 if ( uno::Reference
< task::XInteractionAbort
>( xSelected
.get(), uno::UNO_QUERY
).is() )
961 SetError( ERRCODE_ABORT
, OUString( OSL_LOG_PREFIX
) );
963 else if ( uno::Reference
< task::XInteractionDisapprove
>( xSelected
.get(), uno::UNO_QUERY
).is() )
965 // own lock on loading, user has selected to ignore the lock
966 // own lock on saving, user has selected to ignore the lock
967 // alien lock on loading, user has selected to edit a copy of document
968 // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
969 if ( bIsLoading
&& !bOwnLock
)
971 // means that a copy of the document should be opened
972 GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE
, true ) );
975 nResult
= LOCK_UI_SUCCEEDED
;
977 else // if ( XSelected == aContinuations[1] )
979 // own lock on loading, user has selected to open readonly
980 // own lock on saving, user has selected to open readonly
981 // alien lock on loading, user has selected to retry saving
982 // TODO/LATER: alien lock on saving, user has selected to retry saving
985 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
987 nResult
= LOCK_UI_TRY
;
994 // if no interaction handler is provided the default answer is open readonly
995 // that usually happens in case the document is loaded per API
996 // so the document must be opened readonly for backward compatibility
997 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
1000 SetError( ERRCODE_IO_ACCESSDENIED
, OUString( OSL_LOG_PREFIX
) );
1009 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
1010 bool isSuitableProtocolForLocking(const String
& rLogicName
)
1012 INetURLObject
aUrl( rLogicName
);
1013 INetProtocol eProt
= aUrl
.GetProtocol();
1014 #if HAVE_FEATURE_MACOSX_SANDBOX
1015 return eProt
== INET_PROT_SFTP
;
1017 return eProt
== INET_PROT_FILE
|| eProt
== INET_PROT_SFTP
;
1023 // returns true if the document can be opened for editing ( even if it should be a copy )
1024 // otherwise the document should be opened readonly
1025 // if user cancel the loading the ERROR_ABORT is set
1026 bool SfxMedium::LockOrigFileOnDemand( sal_Bool bLoading
, sal_Bool bNoUI
)
1028 #if !HAVE_FEATURE_MULTIUSER_ENVIRONMENT
1033 if (!IsLockingUsed())
1036 if ( GetURLObject().HasError() )
1039 bool bResult
= false;
1042 if ( pImp
->m_bLocked
&& bLoading
&& ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
1044 // if the document is already locked the system locking might be temporarely off after storing
1045 // check whether the system file locking should be taken again
1046 GetLockingStream_Impl();
1049 bResult
= pImp
->m_bLocked
;
1053 // no read-write access is necessary on loading if the document is explicitly opened as copy
1054 SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem
, SfxBoolItem
, SID_TEMPLATE
, false);
1055 bResult
= ( bLoading
&& pTemplateItem
&& pTemplateItem
->GetValue() );
1058 if ( !bResult
&& !IsReadOnly() )
1060 bool bContentReadonly
= false;
1061 if ( bLoading
&& ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
1063 // let the original document be opened to check the possibility to open it for editing
1064 // and to let the writable stream stay open to hold the lock on the document
1065 GetLockingStream_Impl();
1068 // "IsReadOnly" property does not allow to detect whether the file is readonly always
1069 // so we try always to open the file for editing
1070 // the file is readonly only in case the read-write stream can not be opened
1071 if ( bLoading
&& !pImp
->m_xLockingStream
.is() )
1075 // MediaDescriptor does this check also, the duplication should be avoided in future
1076 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1077 ::ucbhelper::Content
aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, comphelper::getProcessComponentContext() );
1078 aContent
.getPropertyValue( OUString( "IsReadOnly" ) ) >>= bContentReadonly
;
1080 catch( const uno::Exception
& ) {}
1083 // This block was introduced as a fix to i#102464, but removing
1084 // this does not make the problem re-appear. But leaving this
1085 // part would interfere with documents saved in samba share. This
1086 // affects Windows only.
1087 if ( !bContentReadonly
)
1089 // the file is not readonly, check the ACL
1092 if ( ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), aPhysPath
) )
1093 bContentReadonly
= IsReadonlyAccordingACL( aPhysPath
.GetBuffer() );
1097 if ( bContentReadonly
)
1098 pImp
->m_bOriginallyReadOnly
= true;
1101 // do further checks only if the file not readonly in fs
1102 if ( !bContentReadonly
)
1104 // the special file locking should be used only for suitable URLs
1105 if ( isSuitableProtocolForLocking( pImp
->m_aLogicName
) )
1108 // in case of storing the document should request the output before locking
1111 // let the stream be opened to check the system file locking
1115 sal_Int8 bUIStatus
= LOCK_UI_NOLOCK
;
1117 // check whether system file locking has been used, the default value is false
1118 bool bUseSystemLock
= ::utl::LocalFileHelper::IsLocalFile( pImp
->m_aLogicName
) && IsSystemFileLockingUsed();
1120 // TODO/LATER: This implementation does not allow to detect the system lock on saving here, actually this is no big problem
1121 // if system lock is used the writeable stream should be available
1122 bool bHandleSysLocked
= ( bLoading
&& bUseSystemLock
&& !pImp
->xStream
.is() && !pImp
->m_pOutStream
);
1128 ::svt::DocumentLockFile
aLockFile( pImp
->m_aLogicName
);
1129 if ( !bHandleSysLocked
)
1133 bResult
= aLockFile
.CreateOwnLockFile();
1135 catch ( const ucb::InteractiveIOException
& e
)
1137 // exception means that the lock file can not be successfully accessed
1138 // in this case it should be ignored if system file locking is anyway active
1139 if ( bUseSystemLock
|| !IsOOoLockFileUsed() )
1142 // take the ownership over the lock file
1143 aLockFile
.OverwriteOwnLockFile();
1145 else if ( e
.Code
== IOErrorCode_INVALID_PARAMETER
)
1147 // system file locking is not active, ask user whether he wants to open the document without any locking
1148 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
1150 if ( xHandler
.is() )
1152 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xIgnoreRequestImpl
1153 = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
1155 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 2 );
1156 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl
.get() );
1157 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl
.get() );
1158 xIgnoreRequestImpl
->setContinuations( aContinuations
);
1160 xHandler
->handle( xIgnoreRequestImpl
.get() );
1162 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xIgnoreRequestImpl
->getSelection();
1163 bResult
= uno::Reference
< task::XInteractionApprove
>( xSelected
.get(), uno::UNO_QUERY
).is();
1167 catch ( const uno::Exception
& )
1169 // exception means that the lock file can not be successfully accessed
1170 // in this case it should be ignored if system file locking is anyway active
1171 if ( bUseSystemLock
|| !IsOOoLockFileUsed() )
1174 // take the ownership over the lock file
1175 aLockFile
.OverwriteOwnLockFile();
1179 // in case OOo locking is turned off the lock file is still written if possible
1180 // but it is ignored while deciding whether the document should be opened for editing or not
1181 if ( !bResult
&& !IsOOoLockFileUsed() )
1184 // take the ownership over the lock file
1185 aLockFile
.OverwriteOwnLockFile();
1192 uno::Sequence
< OUString
> aData
;
1195 // impossibility to get data is no real problem
1196 aData
= aLockFile
.GetLockData();
1198 catch( const uno::Exception
& )
1202 bool bOwnLock
= false;
1204 if ( !bHandleSysLocked
)
1206 uno::Sequence
< OUString
> aOwnData
= aLockFile
.GenerateOwnEntry();
1207 bOwnLock
= ( aData
.getLength() > LOCKFILE_USERURL_ID
1208 && aOwnData
.getLength() > LOCKFILE_USERURL_ID
1209 && aOwnData
[LOCKFILE_SYSUSERNAME_ID
].equals( aData
[LOCKFILE_SYSUSERNAME_ID
] ) );
1212 && aOwnData
[LOCKFILE_LOCALHOST_ID
].equals( aData
[LOCKFILE_LOCALHOST_ID
] )
1213 && aOwnData
[LOCKFILE_USERURL_ID
].equals( aData
[LOCKFILE_USERURL_ID
] ) )
1215 // this is own lock from the same installation, it could remain because of crash
1220 if ( !bResult
&& !bNoUI
)
1222 bUIStatus
= ShowLockedDocumentDialog( aData
, bLoading
, bOwnLock
);
1223 if ( bUIStatus
== LOCK_UI_SUCCEEDED
)
1225 // take the ownership over the lock file
1226 bResult
= aLockFile
.OverwriteOwnLockFile();
1230 bHandleSysLocked
= false;
1233 catch( const uno::Exception
& )
1236 } while( !bResult
&& bUIStatus
== LOCK_UI_TRY
);
1238 pImp
->m_bLocked
= bResult
;
1242 // this is no file URL, check whether the file is readonly
1243 bResult
= !bContentReadonly
;
1248 if ( !bResult
&& GetError() == ERRCODE_NONE
)
1250 // the error should be set in case it is storing process
1251 // or the document has been opened for editing explicitly
1252 SFX_ITEMSET_ARG( pImp
->m_pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, false );
1254 if ( !bLoading
|| (pReadOnlyItem
&& !pReadOnlyItem
->GetValue()) )
1255 SetError( ERRCODE_IO_ACCESSDENIED
, OUString( OSL_LOG_PREFIX
) );
1257 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
1260 // when the file is locked, get the current file date
1261 if ( bResult
&& DocNeedsFileDateCheck() )
1262 GetInitFileDate( true );
1264 catch( const uno::Exception
& )
1266 OSL_FAIL( "Locking exception: high probability, that the content has not been created" );
1272 //------------------------------------------------------------------
1273 uno::Reference
< embed::XStorage
> SfxMedium::GetStorage( sal_Bool bCreateTempIfNo
)
1275 if ( pImp
->xStorage
.is() || pImp
->m_bTriedStorage
)
1276 return pImp
->xStorage
;
1278 uno::Sequence
< uno::Any
> aArgs( 2 );
1280 // the medium should be retrieved before temporary file creation
1281 // to let the MediaDescriptor be filled with the streams
1284 if ( bCreateTempIfNo
)
1285 CreateTempFile( false );
1290 return pImp
->xStorage
;
1292 SFX_ITEMSET_ARG( GetItemSet(), pRepairItem
, SfxBoolItem
, SID_REPAIRPACKAGE
, false);
1293 if ( pRepairItem
&& pRepairItem
->GetValue() )
1295 // the storage should be created for repairing mode
1296 CreateTempFile( false );
1299 Reference
< ::com::sun::star::ucb::XProgressHandler
> xProgressHandler
;
1300 Reference
< ::com::sun::star::task::XStatusIndicator
> xStatusIndicator
;
1302 SFX_ITEMSET_ARG( GetItemSet(), pxProgressItem
, SfxUnoAnyItem
, SID_PROGRESS_STATUSBAR_CONTROL
, false );
1303 if( pxProgressItem
&& ( pxProgressItem
->GetValue() >>= xStatusIndicator
) )
1304 xProgressHandler
= Reference
< ::com::sun::star::ucb::XProgressHandler
>(
1305 new utl::ProgressHandlerWrap( xStatusIndicator
) );
1307 uno::Sequence
< beans::PropertyValue
> aAddProps( 2 );
1308 aAddProps
[0].Name
= OUString("RepairPackage");
1309 aAddProps
[0].Value
<<= (sal_Bool
)true;
1310 aAddProps
[1].Name
= OUString("StatusIndicator");
1311 aAddProps
[1].Value
<<= xProgressHandler
;
1313 // the first arguments will be filled later
1315 aArgs
[2] <<= aAddProps
;
1318 if ( pImp
->xStream
.is() )
1320 // since the storage is based on temporary stream we open it always read-write
1321 aArgs
[0] <<= pImp
->xStream
;
1322 aArgs
[1] <<= embed::ElementModes::READWRITE
;
1323 pImp
->bStorageBasedOnInStream
= true;
1325 else if ( pImp
->xInputStream
.is() )
1327 // since the storage is based on temporary stream we open it always read-write
1328 aArgs
[0] <<= pImp
->xInputStream
;
1329 aArgs
[1] <<= embed::ElementModes::READ
;
1330 pImp
->bStorageBasedOnInStream
= true;
1334 CloseStreams_Impl();
1335 aArgs
[0] <<= pImp
->m_aName
;
1336 aArgs
[1] <<= embed::ElementModes::READ
;
1337 pImp
->bStorageBasedOnInStream
= false;
1342 pImp
->xStorage
= uno::Reference
< embed::XStorage
>(
1343 ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs
),
1346 catch( const uno::Exception
& )
1348 // impossibility to create the storage is no error
1351 if( ( pImp
->nLastStorageError
= GetError() ) != SVSTREAM_OK
)
1354 if ( pImp
->m_pInStream
)
1355 pImp
->m_pInStream
->Seek(0);
1356 return uno::Reference
< embed::XStorage
>();
1359 pImp
->m_bTriedStorage
= true;
1361 // TODO/LATER: Get versionlist on demand
1362 if ( pImp
->xStorage
.is() )
1364 SetEncryptionDataToStorage_Impl();
1368 SFX_ITEMSET_ARG( pImp
->m_pSet
, pVersion
, SfxInt16Item
, SID_VERSION
, false);
1370 bool bResetStorage
= false;
1371 if ( pVersion
&& pVersion
->GetValue() )
1373 // Read all available versions
1374 if ( pImp
->aVersions
.getLength() )
1376 // Search for the version fits the comment
1377 // The versions are numbered startign with 1, versions with
1378 // negative versions numbers are counted backwards from the
1380 short nVersion
= pVersion
? pVersion
->GetValue() : 0;
1382 nVersion
= ( (short) pImp
->aVersions
.getLength() ) + nVersion
;
1383 else if ( nVersion
)
1386 util::RevisionTag
& rTag
= pImp
->aVersions
[nVersion
];
1388 // Open SubStorage for all versions
1389 uno::Reference
< embed::XStorage
> xSub
= pImp
->xStorage
->openStorageElement( "Versions",
1390 embed::ElementModes::READ
);
1392 DBG_ASSERT( xSub
.is(), "Version list, but no Versions!" );
1394 // There the version is stored as packed Stream
1395 uno::Reference
< io::XStream
> xStr
= xSub
->openStreamElement( rTag
.Identifier
, embed::ElementModes::READ
);
1396 SvStream
* pStream
= utl::UcbStreamHelper::CreateStream( xStr
);
1397 if ( pStream
&& pStream
->GetError() == SVSTREAM_OK
)
1399 // Unpack Stream in TempDir
1400 ::utl::TempFile aTempFile
;
1401 String aTmpName
= aTempFile
.GetURL();
1402 SvFileStream
aTmpStream( aTmpName
, SFX_STREAM_READWRITE
);
1404 *pStream
>> aTmpStream
;
1407 // Open data as Storage
1408 pImp
->m_nStorOpenMode
= SFX_STREAM_READONLY
;
1409 pImp
->xStorage
= comphelper::OStorageHelper::GetStorageFromURL( aTmpName
, embed::ElementModes::READ
);
1410 pImp
->bStorageBasedOnInStream
= false;
1412 ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName
, aTemp
);
1413 SetPhysicalName_Impl( aTemp
);
1415 pImp
->bIsTemp
= true;
1416 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
1418 pImp
->aVersions
.realloc(0);
1421 bResetStorage
= true;
1425 bResetStorage
= true;
1428 if ( bResetStorage
)
1430 pImp
->xStorage
.clear();
1431 if ( pImp
->m_pInStream
)
1432 pImp
->m_pInStream
->Seek( 0L );
1435 pImp
->bIsStorage
= pImp
->xStorage
.is();
1436 return pImp
->xStorage
;
1439 //------------------------------------------------------------------
1440 uno::Reference
< embed::XStorage
> SfxMedium::GetZipStorageToSign_Impl( sal_Bool bReadOnly
)
1442 if ( !GetError() && !pImp
->m_xZipStorage
.is() )
1448 // we can not sign document if there is no stream
1449 // should it be possible at all?
1450 if ( !bReadOnly
&& pImp
->xStream
.is() )
1452 pImp
->m_xZipStorage
= ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xStream
, embed::ElementModes::READWRITE
);
1454 else if ( pImp
->xInputStream
.is() )
1456 pImp
->m_xZipStorage
= ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xInputStream
);
1459 catch( const uno::Exception
& )
1461 OSL_FAIL( "No possibility to get readonly version of storage from medium!\n" );
1464 if ( GetError() ) // do not remove warnings
1468 return pImp
->m_xZipStorage
;
1471 //------------------------------------------------------------------
1472 void SfxMedium::CloseZipStorage_Impl()
1474 if ( pImp
->m_xZipStorage
.is() )
1477 pImp
->m_xZipStorage
->dispose();
1478 } catch( const uno::Exception
& )
1481 pImp
->m_xZipStorage
.clear();
1485 void SfxMedium::CloseStorage()
1487 if ( pImp
->xStorage
.is() )
1489 uno::Reference
< lang::XComponent
> xComp( pImp
->xStorage
, uno::UNO_QUERY
);
1490 // in the salvage mode the medium does not own the storage
1491 if ( pImp
->bDisposeStorage
&& !pImp
->m_bSalvageMode
)
1495 } catch( const uno::Exception
& )
1497 OSL_FAIL( "Medium's storage is already disposed!\n" );
1501 pImp
->xStorage
.clear();
1502 pImp
->bStorageBasedOnInStream
= false;
1505 pImp
->m_bTriedStorage
= false;
1506 pImp
->bIsStorage
= false;
1509 void SfxMedium::CanDisposeStorage_Impl( sal_Bool bDisposeStorage
)
1511 pImp
->bDisposeStorage
= bDisposeStorage
;
1514 sal_Bool
SfxMedium::WillDisposeStorageOnClose_Impl()
1516 return pImp
->bDisposeStorage
;
1519 StreamMode
SfxMedium::GetOpenMode() const
1521 return pImp
->m_nStorOpenMode
;
1524 void SfxMedium::SetOpenMode( StreamMode nStorOpen
,
1525 sal_Bool bDontClose
)
1527 if ( pImp
->m_nStorOpenMode
!= nStorOpen
)
1529 pImp
->m_nStorOpenMode
= nStorOpen
;
1533 if ( pImp
->xStorage
.is() )
1536 CloseStreams_Impl();
1541 //------------------------------------------------------------------
1542 sal_Bool
SfxMedium::UseBackupToRestore_Impl( ::ucbhelper::Content
& aOriginalContent
,
1543 const Reference
< ::com::sun::star::ucb::XCommandEnvironment
>& xComEnv
)
1547 ::ucbhelper::Content
aTransactCont( pImp
->m_aBackupURL
, xComEnv
, comphelper::getProcessComponentContext() );
1549 Reference
< XInputStream
> aOrigInput
= aTransactCont
.openStream();
1550 aOriginalContent
.writeStream( aOrigInput
, true );
1553 catch( const Exception
& )
1555 // in case of failure here the backup file should not be removed
1556 // TODO/LATER: a message should be used to let user know about the backup
1557 pImp
->m_bRemoveBackup
= false;
1558 // TODO/LATER: needs a specific error code
1559 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1565 //------------------------------------------------------------------
1566 sal_Bool
SfxMedium::StorageCommit_Impl()
1568 bool bResult
= false;
1569 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1570 ::ucbhelper::Content aOriginalContent
;
1572 if ( pImp
->xStorage
.is() )
1576 uno::Reference
< embed::XTransactedObject
> xTrans( pImp
->xStorage
, uno::UNO_QUERY
);
1582 CloseZipStorage_Impl();
1585 catch ( const embed::UseBackupException
& aBackupExc
)
1587 // since the temporary file is created always now, the scenario is close to be impossible
1588 if ( !pImp
->pTempFile
)
1590 OSL_ENSURE( !pImp
->m_aBackupURL
.isEmpty(), "No backup on storage commit!\n" );
1591 if ( !pImp
->m_aBackupURL
.isEmpty()
1592 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
),
1593 xDummyEnv
, comphelper::getProcessComponentContext(),
1594 aOriginalContent
) )
1596 // use backup to restore the file
1597 // the storage has already disconnected from original location
1598 CloseAndReleaseStreams_Impl();
1599 if ( !UseBackupToRestore_Impl( aOriginalContent
, xDummyEnv
) )
1601 // connect the medium to the temporary file of the storage
1602 pImp
->aContent
= ::ucbhelper::Content();
1603 pImp
->m_aName
= aBackupExc
.TemporaryFileURL
;
1604 OSL_ENSURE( !pImp
->m_aName
.isEmpty(), "The exception _must_ contain the temporary URL!\n" );
1609 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1612 catch ( const uno::Exception
& )
1614 //TODO/LATER: improve error handling
1615 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1624 //------------------------------------------------------------------
1625 sal_Bool
SfxMedium::TransactedTransferForFS_Impl( const INetURLObject
& aSource
,
1626 const INetURLObject
& aDest
,
1627 const Reference
< ::com::sun::star::ucb::XCommandEnvironment
>& xComEnv
)
1629 bool bResult
= false;
1630 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1631 Reference
< XOutputStream
> aDestStream
;
1632 ::ucbhelper::Content aOriginalContent
;
1636 aOriginalContent
= ::ucbhelper::Content( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
, comphelper::getProcessComponentContext() );
1638 catch ( const ::com::sun::star::ucb::CommandAbortedException
& )
1640 pImp
->m_eError
= ERRCODE_ABORT
;
1642 catch ( const ::com::sun::star::ucb::CommandFailedException
& )
1644 pImp
->m_eError
= ERRCODE_ABORT
;
1646 catch (const ::com::sun::star::ucb::ContentCreationException
& ex
)
1648 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1650 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER
) ||
1651 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED
)
1654 pImp
->m_eError
= ERRCODE_IO_NOTEXISTSPATH
;
1657 catch (const ::com::sun::star::uno::Exception
&)
1659 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1662 if( !pImp
->m_eError
|| (pImp
->m_eError
& ERRCODE_WARNING_MASK
) )
1664 if ( pImp
->xStorage
.is() )
1667 CloseStreams_Impl();
1669 ::ucbhelper::Content aTempCont
;
1670 if( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, comphelper::getProcessComponentContext(), aTempCont
) )
1672 bool bTransactStarted
= false;
1673 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, false );
1674 SFX_ITEMSET_ARG( GetItemSet(), pRename
, SfxBoolItem
, SID_RENAME
, false );
1675 bool bRename
= pRename
? pRename
->GetValue() : false;
1676 bool bOverWrite
= pOverWrite
? pOverWrite
->GetValue() : !bRename
;
1680 if( bOverWrite
&& ::utl::UCBContentHelper::IsDocument( aDest
.GetMainURL( INetURLObject::NO_DECODE
) ) )
1682 if( pImp
->m_aBackupURL
.isEmpty() )
1683 DoInternalBackup_Impl( aOriginalContent
);
1685 if( !pImp
->m_aBackupURL
.isEmpty() )
1687 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1688 bTransactStarted
= true;
1689 aOriginalContent
.setPropertyValue( "Size", uno::makeAny( (sal_Int64
)0 ) );
1690 aOriginalContent
.writeStream( aTempInput
, bOverWrite
);
1695 pImp
->m_eError
= ERRCODE_SFX_CANTCREATEBACKUP
;
1700 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1701 aOriginalContent
.writeStream( aTempInput
, bOverWrite
);
1705 catch ( const ::com::sun::star::ucb::CommandAbortedException
& )
1707 pImp
->m_eError
= ERRCODE_ABORT
;
1709 catch ( const ::com::sun::star::ucb::CommandFailedException
& )
1711 pImp
->m_eError
= ERRCODE_ABORT
;
1713 catch ( const ::com::sun::star::ucb::InteractiveIOException
& r
)
1715 if ( r
.Code
== IOErrorCode_ACCESS_DENIED
)
1716 pImp
->m_eError
= ERRCODE_IO_ACCESSDENIED
;
1717 else if ( r
.Code
== IOErrorCode_NOT_EXISTING
)
1718 pImp
->m_eError
= ERRCODE_IO_NOTEXISTS
;
1719 else if ( r
.Code
== IOErrorCode_CANT_READ
)
1720 pImp
->m_eError
= ERRCODE_IO_CANTREAD
;
1722 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1724 catch ( const ::com::sun::star::uno::Exception
& )
1726 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
1731 if ( pImp
->pTempFile
)
1733 pImp
->pTempFile
->EnableKillingFile( true );
1734 delete pImp
->pTempFile
;
1735 pImp
->pTempFile
= NULL
;
1738 else if ( bTransactStarted
)
1740 UseBackupToRestore_Impl( aOriginalContent
, xDummyEnv
);
1744 pImp
->m_eError
= ERRCODE_IO_CANTREAD
;
1750 //------------------------------------------------------------------
1751 sal_Bool
SfxMedium::TryDirectTransfer( const OUString
& aURL
, SfxItemSet
& aTargetSet
)
1756 // if the document had no password it should be stored without password
1757 // if the document had password it should be stored with the same password
1758 // otherwise the stream copying can not be done
1759 SFX_ITEMSET_ARG( &aTargetSet
, pNewPassItem
, SfxStringItem
, SID_PASSWORD
, false );
1760 SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem
, SfxStringItem
, SID_PASSWORD
, false );
1761 if ( ( !pNewPassItem
&& !pOldPassItem
)
1762 || ( pNewPassItem
&& pOldPassItem
&& pNewPassItem
->GetValue() == pOldPassItem
->GetValue() ) )
1764 // the filter must be the same
1765 SFX_ITEMSET_ARG( &aTargetSet
, pNewFilterItem
, SfxStringItem
, SID_FILTER_NAME
, false );
1766 SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem
, SfxStringItem
, SID_FILTER_NAME
, false );
1767 if ( pNewFilterItem
&& pOldFilterItem
&& pNewFilterItem
->GetValue() == pOldFilterItem
->GetValue() )
1769 // get the input stream and copy it
1770 // in case of success return true
1771 uno::Reference
< io::XInputStream
> xInStream
= GetInputStream();
1774 if ( xInStream
.is() )
1778 uno::Reference
< io::XSeekable
> xSeek( xInStream
, uno::UNO_QUERY
);
1782 nPos
= xSeek
->getPosition();
1786 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
1787 ::ucbhelper::Content
aTargetContent( aURL
, xEnv
, comphelper::getProcessComponentContext() );
1789 InsertCommandArgument aInsertArg
;
1790 aInsertArg
.Data
= xInStream
;
1791 SFX_ITEMSET_ARG( &aTargetSet
, pRename
, SfxBoolItem
, SID_RENAME
, false );
1792 SFX_ITEMSET_ARG( &aTargetSet
, pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, false );
1793 if ( (pOverWrite
&& !pOverWrite
->GetValue()) // argument says: never overwrite
1794 || (pRename
&& pRename
->GetValue()) ) // argument says: rename file
1795 aInsertArg
.ReplaceExisting
= false;
1797 aInsertArg
.ReplaceExisting
= true; // default is overwrite existing files
1800 aCmdArg
<<= aInsertArg
;
1801 aTargetContent
.executeCommand( OUString( "insert" ),
1805 xSeek
->seek( nPos
);
1809 catch( const uno::Exception
& )
1818 //------------------------------------------------------------------
1819 void SfxMedium::Transfer_Impl()
1821 // The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
1823 if ( pImp
->pTempFile
)
1824 aNameURL
= pImp
->pTempFile
->GetURL();
1825 else if ( !pImp
->m_aLogicName
.isEmpty() && pImp
->m_bSalvageMode
)
1827 // makes sence only in case logic name is set
1828 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aNameURL
) )
1829 OSL_FAIL( "The medium name is not convertible!\n" );
1832 if ( !aNameURL
.isEmpty() && ( !pImp
->m_eError
|| (pImp
->m_eError
& ERRCODE_WARNING_MASK
) ) )
1834 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::Transfer_Impl, copying to target" );
1836 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
1837 Reference
< XOutputStream
> rOutStream
;
1839 // in case an output stream is provided from outside and the URL is correct
1840 // commit to the stream
1841 if (pImp
->m_aLogicName
.startsWith("private:stream"))
1843 // TODO/LATER: support storing to SID_STREAM
1844 SFX_ITEMSET_ARG( pImp
->m_pSet
, pOutStreamItem
, SfxUnoAnyItem
, SID_OUTPUTSTREAM
, false);
1845 if( pOutStreamItem
&& ( pOutStreamItem
->GetValue() >>= rOutStream
) )
1847 if ( pImp
->xStorage
.is() )
1850 CloseStreams_Impl();
1852 INetURLObject
aSource( aNameURL
);
1853 ::ucbhelper::Content aTempCont
;
1854 if( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext(), aTempCont
) )
1859 sal_Int32 nBufferSize
= 32767;
1860 Sequence
< sal_Int8
> aSequence ( nBufferSize
);
1861 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1865 nRead
= aTempInput
->readBytes ( aSequence
, nBufferSize
);
1866 if ( nRead
< nBufferSize
)
1868 Sequence
< sal_Int8
> aTempBuf ( aSequence
.getConstArray(), nRead
);
1869 rOutStream
->writeBytes ( aTempBuf
);
1872 rOutStream
->writeBytes ( aSequence
);
1874 while ( nRead
== nBufferSize
);
1876 // remove temporary file
1877 if ( pImp
->pTempFile
)
1879 pImp
->pTempFile
->EnableKillingFile( true );
1880 delete pImp
->pTempFile
;
1881 pImp
->pTempFile
= NULL
;
1884 catch( const Exception
& )
1890 OSL_FAIL( "Illegal Output stream parameter!\n" );
1891 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1894 // free the reference
1896 pImp
->m_pSet
->ClearItem( SID_OUTPUTSTREAM
);
1902 if ( !pImp
->aContent
.get().is() )
1904 pImp
->m_eError
= ERRCODE_IO_NOTEXISTS
;
1908 SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize
, SfxInt32Item
, SID_SEGMENTSIZE
, false);
1911 // this file must be stored into a disk spanned package
1914 uno::Reference
< embed::XStorage
> xStor
= comphelper::OStorageHelper::GetStorageFromURL( GetName(),
1915 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1917 // set segment size property; package will automatically be divided in pieces fitting
1919 ::com::sun::star::uno::Any aAny
;
1920 aAny
<<= pSegmentSize
->GetValue();
1922 uno::Reference
< beans::XPropertySet
> xSet( pImp
->xStorage
, uno::UNO_QUERY
);
1923 xSet
->setPropertyValue( OUString("SegmentSize"), aAny
);
1925 // copy the temporary storage into the disk spanned package
1926 GetStorage()->copyToStorage( xStor
);
1927 uno::Reference
< embed::XTransactedObject
> xTrans( pImp
->xStorage
, uno::UNO_QUERY
);
1932 catch ( const uno::Exception
& )
1934 //TODO/MBA: error handling
1939 INetURLObject
aDest( GetURLObject() );
1941 // source is the temp file written so far
1942 INetURLObject
aSource( aNameURL
);
1944 // a special case, an interaction handler should be used for
1945 // authentication in case it is available
1946 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
1947 Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler
= GetInteractionHandler();
1948 if (xInteractionHandler
.is())
1949 xComEnv
= new ::ucbhelper::CommandEnvironment( xInteractionHandler
,
1950 Reference
< ::com::sun::star::ucb::XProgressHandler
>() );
1952 OUString
aDestURL( aDest
.GetMainURL( INetURLObject::NO_DECODE
) );
1954 if ( ::utl::LocalFileHelper::IsLocalFile( aDestURL
) || !aDest
.removeSegment() )
1956 TransactedTransferForFS_Impl( aSource
, aDest
, xComEnv
);
1958 // Hideous - no clean way to do this, so we re-open the file just to fsync it
1959 osl::File
aFile( aDestURL
);
1960 if ( aFile
.open( osl_File_OpenFlag_Write
) == osl::FileBase::E_None
)
1963 OSL_TRACE("fsync'd saved file '%s'\n",
1964 OUStringToOString( aDestURL
, RTL_TEXTENCODING_UTF8
).getStr() );
1970 // create content for the parent folder and call transfer on that content with the source content
1971 // and the destination file name as parameters
1972 ::ucbhelper::Content aSourceContent
;
1973 ::ucbhelper::Content aTransferContent
;
1975 ::ucbhelper::Content aDestContent
;
1976 ::ucbhelper::Content::create( aDestURL
, xComEnv
, comphelper::getProcessComponentContext(), aDestContent
);
1977 // For checkin, we need the object URL, not the parent folder:
1978 if ( !IsInCheckIn( ) )
1980 // Get the parent URL from the XChild if possible: why would the URL necessarily have
1981 // a hierarchical path? It's not always the case for CMIS.
1982 Reference
< ::com::sun::star::container::XChild
> xChild( aDestContent
.get(), uno::UNO_QUERY
);
1983 OUString sParentUrl
;
1986 Reference
< ::com::sun::star::ucb::XContent
> xParent( xChild
->getParent( ), uno::UNO_QUERY
);
1987 if ( xParent
.is( ) )
1989 sParentUrl
= xParent
->getIdentifier( )->getContentIdentifier();
1993 if ( sParentUrl
.isEmpty() )
1994 aDestURL
= aDest
.GetMainURL( INetURLObject::NO_DECODE
);
1995 // adjust to above aDest.removeSegment()
1997 aDestURL
= sParentUrl
;
2000 // LongName wasn't defined anywhere, only used here... get the Title instead
2001 // as it's less probably empty
2003 Any aAny
= aDestContent
.getPropertyValue( OUString("Title" ) );
2005 if ( aFileName
.isEmpty() )
2006 aFileName
= GetURLObject().getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2010 aTransferContent
= ::ucbhelper::Content( aDestURL
, xComEnv
, comphelper::getProcessComponentContext() );
2012 catch (const ::com::sun::star::ucb::ContentCreationException
& ex
)
2014 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2016 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER
) ||
2017 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED
)
2020 pImp
->m_eError
= ERRCODE_IO_NOTEXISTSPATH
;
2023 catch (const ::com::sun::star::uno::Exception
&)
2025 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2028 if ( !pImp
->m_eError
|| (pImp
->m_eError
& ERRCODE_WARNING_MASK
) )
2030 // free resources, otherwise the transfer may fail
2031 if ( pImp
->xStorage
.is() )
2034 CloseStreams_Impl();
2036 ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext(), aSourceContent
);
2038 // check for external parameters that may customize the handling of NameClash situations
2039 SFX_ITEMSET_ARG( GetItemSet(), pRename
, SfxBoolItem
, SID_RENAME
, false );
2040 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, false );
2041 sal_Int32 nNameClash
;
2042 if ( pOverWrite
&& !pOverWrite
->GetValue() )
2043 // argument says: never overwrite
2044 nNameClash
= NameClash::ERROR
;
2045 else if ( pRename
&& pRename
->GetValue() )
2046 // argument says: rename file
2047 nNameClash
= NameClash::RENAME
;
2049 // default is overwrite existing files
2050 nNameClash
= NameClash::OVERWRITE
;
2054 OUString aMimeType
= pImp
->getFilterMimeType();
2055 ::ucbhelper::InsertOperation eOperation
= ::ucbhelper::InsertOperation_COPY
;
2056 bool bMajor
= false;
2058 if ( IsInCheckIn( ) )
2060 eOperation
= ::ucbhelper::InsertOperation_CHECKIN
;
2061 SFX_ITEMSET_ARG( GetItemSet(), pMajor
, SfxBoolItem
, SID_DOCINFO_MAJOR
, false );
2062 bMajor
= pMajor
&& pMajor
->GetValue( );
2063 SFX_ITEMSET_ARG( GetItemSet(), pComments
, SfxStringItem
, SID_DOCINFO_COMMENTS
, false );
2065 sComment
= pComments
->GetValue( );
2067 OUString sResultURL
;
2068 if (!aTransferContent
.transferContent( aSourceContent
, eOperation
,
2069 aFileName
, nNameClash
, aMimeType
, bMajor
, sComment
, &sResultURL
))
2070 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2071 else if ( !sResultURL
.isEmpty( ) ) // Likely to happen only for checkin
2072 SwitchDocumentToFile( sResultURL
);
2074 catch ( const ::com::sun::star::ucb::CommandAbortedException
& )
2076 pImp
->m_eError
= ERRCODE_ABORT
;
2078 catch ( const ::com::sun::star::ucb::CommandFailedException
& )
2080 pImp
->m_eError
= ERRCODE_ABORT
;
2082 catch ( const ::com::sun::star::ucb::InteractiveIOException
& r
)
2084 if ( r
.Code
== IOErrorCode_ACCESS_DENIED
)
2085 pImp
->m_eError
= ERRCODE_IO_ACCESSDENIED
;
2086 else if ( r
.Code
== IOErrorCode_NOT_EXISTING
)
2087 pImp
->m_eError
= ERRCODE_IO_NOTEXISTS
;
2088 else if ( r
.Code
== IOErrorCode_CANT_READ
)
2089 pImp
->m_eError
= ERRCODE_IO_CANTREAD
;
2091 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2093 catch ( const ::com::sun::star::uno::Exception
& )
2095 pImp
->m_eError
= ERRCODE_IO_GENERAL
;
2098 // do not switch from temporary file in case of nonfile protocol
2102 if ( ( !pImp
->m_eError
|| (pImp
->m_eError
& ERRCODE_WARNING_MASK
) ) && !pImp
->pTempFile
)
2104 // without a TempFile the physical and logical name should be the same after successful transfer
2105 ::utl::LocalFileHelper::ConvertURLToPhysicalName(
2106 GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), pImp
->m_aName
);
2107 pImp
->m_bSalvageMode
= false;
2112 //------------------------------------------------------------------
2113 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content
& aOriginalContent
,
2114 const String
& aPrefix
,
2115 const String
& aExtension
,
2116 const String
& aDestDir
)
2118 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::DoInternalBackup_Impl( with destdir )" );
2120 if ( !pImp
->m_aBackupURL
.isEmpty() )
2121 return; // the backup was done already
2123 ::utl::TempFile
aTransactTemp( aPrefix
, &aExtension
, &aDestDir
);
2124 aTransactTemp
.EnableKillingFile( false );
2126 INetURLObject
aBackObj( aTransactTemp
.GetURL() );
2127 OUString aBackupName
= aBackObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2129 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
2130 ::ucbhelper::Content aBackupCont
;
2131 if( ::ucbhelper::Content::create( aDestDir
, xDummyEnv
, comphelper::getProcessComponentContext(), aBackupCont
) )
2135 OUString sMimeType
= pImp
->getFilterMimeType();
2136 if( aBackupCont
.transferContent( aOriginalContent
,
2137 ::ucbhelper::InsertOperation_COPY
,
2139 NameClash::OVERWRITE
,
2142 pImp
->m_aBackupURL
= aBackObj
.GetMainURL( INetURLObject::NO_DECODE
);
2143 pImp
->m_bRemoveBackup
= true;
2146 catch( const Exception
& )
2150 if ( pImp
->m_aBackupURL
.isEmpty() )
2151 aTransactTemp
.EnableKillingFile( true );
2154 //------------------------------------------------------------------
2155 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content
& aOriginalContent
)
2157 if ( !pImp
->m_aBackupURL
.isEmpty() )
2158 return; // the backup was done already
2160 OUString aFileName
= GetURLObject().getName( INetURLObject::LAST_SEGMENT
,
2162 INetURLObject::NO_DECODE
);
2164 sal_Int32 nPrefixLen
= aFileName
.lastIndexOf( '.' );
2165 String aPrefix
= ( nPrefixLen
== -1 ) ? aFileName
: aFileName
.copy( 0, nPrefixLen
);
2166 String aExtension
= ( nPrefixLen
== -1 ) ? String() : String(aFileName
.copy( nPrefixLen
));
2167 String aBakDir
= SvtPathOptions().GetBackupPath();
2169 // create content for the parent folder ( = backup folder )
2170 ::ucbhelper::Content aContent
;
2171 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
2172 if( ::utl::UCBContentHelper::ensureFolder(comphelper::getProcessComponentContext(), xEnv
, aBakDir
, aContent
) )
2173 DoInternalBackup_Impl( aOriginalContent
, aPrefix
, aExtension
, aBakDir
);
2175 if ( pImp
->m_aBackupURL
.isEmpty() )
2177 // the copiing to the backup catalog failed ( for example because
2178 // of using an encrypted partition as target catalog )
2179 // since the user did not specify to make backup explicitly
2180 // office should try to make backup in another place,
2181 // target catalog does not look bad for this case ( and looks
2182 // to be the only way for encrypted partitions )
2184 INetURLObject aDest
= GetURLObject();
2185 if ( aDest
.removeSegment() )
2186 DoInternalBackup_Impl( aOriginalContent
, aPrefix
, aExtension
, aDest
.GetMainURL( INetURLObject::NO_DECODE
) );
2191 //------------------------------------------------------------------
2192 void SfxMedium::DoBackup_Impl()
2194 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::DoBackup_Impl" );
2196 // source file name is the logical name of this medium
2197 INetURLObject
aSource( GetURLObject() );
2199 // there is nothing to backup in case source file does not exist
2200 if ( !::utl::UCBContentHelper::IsDocument( aSource
.GetMainURL( INetURLObject::NO_DECODE
) ) )
2203 bool bSuccess
= false;
2205 // get path for backups
2206 String aBakDir
= SvtPathOptions().GetBackupPath();
2209 // create content for the parent folder ( = backup folder )
2210 ::ucbhelper::Content aContent
;
2211 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
2212 if( ::utl::UCBContentHelper::ensureFolder(comphelper::getProcessComponentContext(), xEnv
, aBakDir
, aContent
) )
2214 // save as ".bak" file
2215 INetURLObject
aDest( aBakDir
);
2216 aDest
.insertName( aSource
.getName() );
2217 aDest
.setExtension( "bak" );
2218 String aFileName
= aDest
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2220 // create a content for the source file
2221 ::ucbhelper::Content aSourceContent
;
2222 if ( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, comphelper::getProcessComponentContext(), aSourceContent
) )
2226 // do the transfer ( copy source file to backup dir )
2227 OUString sMimeType
= pImp
->getFilterMimeType();
2228 bSuccess
= aContent
.transferContent( aSourceContent
,
2229 ::ucbhelper::InsertOperation_COPY
,
2231 NameClash::OVERWRITE
,
2235 pImp
->m_aBackupURL
= aDest
.GetMainURL( INetURLObject::NO_DECODE
);
2236 pImp
->m_bRemoveBackup
= false;
2239 catch ( const ::com::sun::star::uno::Exception
& )
2248 pImp
->m_eError
= ERRCODE_SFX_CANTCREATEBACKUP
;
2252 //------------------------------------------------------------------
2253 void SfxMedium::ClearBackup_Impl()
2255 if( pImp
->m_bRemoveBackup
)
2257 // currently a document is always stored in a new medium,
2258 // thus if a backup can not be removed the backup URL should not be cleaned
2259 if ( !pImp
->m_aBackupURL
.isEmpty() )
2261 if ( ::utl::UCBContentHelper::Kill( pImp
->m_aBackupURL
) )
2263 pImp
->m_bRemoveBackup
= false;
2264 pImp
->m_aBackupURL
= OUString();
2269 OSL_FAIL("Couldn't remove backup file!");
2274 pImp
->m_aBackupURL
= OUString();
2277 //----------------------------------------------------------------
2278 void SfxMedium::GetLockingStream_Impl()
2280 if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
2281 && !pImp
->m_xLockingStream
.is() )
2283 SFX_ITEMSET_ARG( pImp
->m_pSet
, pWriteStreamItem
, SfxUnoAnyItem
, SID_STREAM
, false);
2284 if ( pWriteStreamItem
)
2285 pWriteStreamItem
->GetValue() >>= pImp
->m_xLockingStream
;
2287 if ( !pImp
->m_xLockingStream
.is() )
2289 // open the original document
2290 uno::Sequence
< beans::PropertyValue
> xProps
;
2291 TransformItems( SID_OPENDOC
, *GetItemSet(), xProps
);
2292 comphelper::MediaDescriptor
aMedium( xProps
);
2294 aMedium
.addInputStreamOwnLock();
2296 uno::Reference
< io::XInputStream
> xInputStream
;
2297 aMedium
[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp
->m_xLockingStream
;
2298 aMedium
[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream
;
2300 if ( !pImp
->pTempFile
&& pImp
->m_aName
.isEmpty() )
2302 // the medium is still based on the original file, it makes sence to initialize the streams
2303 if ( pImp
->m_xLockingStream
.is() )
2304 pImp
->xStream
= pImp
->m_xLockingStream
;
2306 if ( xInputStream
.is() )
2307 pImp
->xInputStream
= xInputStream
;
2309 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2310 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2316 //----------------------------------------------------------------
2317 void SfxMedium::GetMedium_Impl()
2319 if ( !pImp
->m_pInStream
)
2321 pImp
->bDownloadDone
= false;
2322 Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler
= GetInteractionHandler();
2324 //TODO/MBA: need support for SID_STREAM
2325 SFX_ITEMSET_ARG( pImp
->m_pSet
, pWriteStreamItem
, SfxUnoAnyItem
, SID_STREAM
, false);
2326 SFX_ITEMSET_ARG( pImp
->m_pSet
, pInStreamItem
, SfxUnoAnyItem
, SID_INPUTSTREAM
, false);
2327 if ( pWriteStreamItem
)
2329 pWriteStreamItem
->GetValue() >>= pImp
->xStream
;
2331 if ( pInStreamItem
)
2332 pInStreamItem
->GetValue() >>= pImp
->xInputStream
;
2334 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2335 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2337 else if ( pInStreamItem
)
2339 pInStreamItem
->GetValue() >>= pImp
->xInputStream
;
2343 uno::Sequence
< beans::PropertyValue
> xProps
;
2345 if (!pImp
->m_aName
.isEmpty())
2347 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aFileName
) )
2349 OSL_FAIL("Physical name not convertible!");
2353 aFileName
= GetName();
2355 // in case the temporary file exists the streams should be initialized from it,
2356 // but the original MediaDescriptor should not be changed
2357 bool bFromTempFile
= ( pImp
->pTempFile
!= NULL
);
2359 if ( !bFromTempFile
)
2361 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, aFileName
) );
2362 if( !(pImp
->m_nStorOpenMode
& STREAM_WRITE
) )
2363 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
2364 if (xInteractionHandler
.is())
2365 GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER
, makeAny(xInteractionHandler
) ) );
2368 if ( pImp
->m_xInputStreamToLoadFrom
.is() )
2370 pImp
->xInputStream
= pImp
->m_xInputStreamToLoadFrom
;
2371 pImp
->xInputStream
->skipBytes(0);
2372 if (pImp
->m_bInputStreamIsReadOnly
)
2373 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, true ) );
2377 TransformItems( SID_OPENDOC
, *GetItemSet(), xProps
);
2378 comphelper::MediaDescriptor
aMedium( xProps
);
2380 if ( pImp
->m_xLockingStream
.is() && !bFromTempFile
)
2382 // the medium is not based on the temporary file, so the original stream can be used
2383 pImp
->xStream
= pImp
->m_xLockingStream
;
2387 if ( bFromTempFile
)
2389 aMedium
[comphelper::MediaDescriptor::PROP_URL()] <<= OUString( aFileName
);
2390 aMedium
.erase( comphelper::MediaDescriptor::PROP_READONLY() );
2391 aMedium
.addInputStream();
2393 else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
2395 // use the special locking approach only for file URLs
2396 aMedium
.addInputStreamOwnLock();
2399 aMedium
.addInputStream();
2401 // the ReadOnly property set in aMedium is ignored
2402 // the check is done in LockOrigFileOnDemand() for file and non-file URLs
2404 //TODO/MBA: what happens if property is not there?!
2405 aMedium
[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp
->xStream
;
2406 aMedium
[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp
->xInputStream
;
2410 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2411 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2414 if ( !bFromTempFile
)
2416 //TODO/MBA: need support for SID_STREAM
2417 if ( pImp
->xStream
.is() )
2418 GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM
, makeAny( pImp
->xStream
) ) );
2420 GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM
, makeAny( pImp
->xInputStream
) ) );
2424 //TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
2425 if ( !GetError() && !pImp
->xStream
.is() && !pImp
->xInputStream
.is() )
2426 SetError( ERRCODE_IO_ACCESSDENIED
, OUString( OSL_LOG_PREFIX
) );
2430 if ( pImp
->xStream
.is() )
2431 pImp
->m_pInStream
= utl::UcbStreamHelper::CreateStream( pImp
->xStream
);
2432 else if ( pImp
->xInputStream
.is() )
2433 pImp
->m_pInStream
= utl::UcbStreamHelper::CreateStream( pImp
->xInputStream
);
2436 pImp
->bDownloadDone
= true;
2437 pImp
->aDoneLink
.ClearPendingCall();
2438 sal_uIntPtr nError
= GetError();
2439 pImp
->aDoneLink
.Call( (void*)nError
);
2443 //----------------------------------------------------------------
2444 sal_Bool
SfxMedium::IsRemote()
2446 return pImp
->m_bRemote
;
2449 //------------------------------------------------------------------
2451 void SfxMedium::SetUpdatePickList(sal_Bool bVal
)
2453 pImp
->bUpdatePickList
= bVal
;
2455 //------------------------------------------------------------------
2457 sal_Bool
SfxMedium::IsUpdatePickList() const
2459 return pImp
->bUpdatePickList
;
2462 void SfxMedium::SetLongName(const OUString
&rName
)
2464 pImp
->m_aLongName
= rName
;
2467 const OUString
& SfxMedium::GetLongName() const
2469 return pImp
->m_aLongName
;
2472 void SfxMedium::SetDoneLink( const Link
& rLink
)
2474 pImp
->aDoneLink
= rLink
;
2477 void SfxMedium::DownLoad( const Link
& aLink
)
2479 SetDoneLink( aLink
);
2481 if ( pImp
->m_pInStream
&& !aLink
.IsSet() )
2483 while( !pImp
->bDownloadDone
)
2484 Application::Yield();
2488 //------------------------------------------------------------------
2489 void SfxMedium::Init_Impl()
2491 Includes a valid:: sun:: com:: star:: util:: URL (If a file name was
2492 previously in there) in the logical name and if available sets the
2493 physical name as the file name.
2497 Reference
< XOutputStream
> rOutStream
;
2499 // TODO/LATER: handle lifetime of storages
2500 pImp
->bDisposeStorage
= false;
2502 SFX_ITEMSET_ARG( pImp
->m_pSet
, pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, false);
2503 if ( pSalvageItem
&& pSalvageItem
->GetValue().isEmpty() )
2505 pSalvageItem
= NULL
;
2506 pImp
->m_pSet
->ClearItem( SID_DOC_SALVAGE
);
2509 if (!pImp
->m_aLogicName
.isEmpty())
2511 INetURLObject
aUrl( pImp
->m_aLogicName
);
2512 INetProtocol eProt
= aUrl
.GetProtocol();
2513 if ( eProt
== INET_PROT_NOT_VALID
)
2515 OSL_FAIL( "Unknown protocol!" );
2519 if ( aUrl
.HasMark() )
2521 pImp
->m_aLogicName
= aUrl
.GetURLNoMark( INetURLObject::NO_DECODE
);
2522 GetItemSet()->Put( SfxStringItem( SID_JUMPMARK
, aUrl
.GetMark() ) );
2525 // try to convert the URL into a physical name - but never change a physical name
2526 // physical name may be set if the logical name is changed after construction
2527 if ( pImp
->m_aName
.isEmpty() )
2528 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), pImp
->m_aName
);
2531 DBG_ASSERT( pSalvageItem
, "Suspicious change of logical name!" );
2536 if ( pSalvageItem
&& !pSalvageItem
->GetValue().isEmpty() )
2538 pImp
->m_aLogicName
= pSalvageItem
->GetValue();
2539 DELETEZ( pImp
->m_pURLObj
);
2540 pImp
->m_bSalvageMode
= true;
2543 // in case output stream is by mistake here
2544 // clear the reference
2545 SFX_ITEMSET_ARG( pImp
->m_pSet
, pOutStreamItem
, SfxUnoAnyItem
, SID_OUTPUTSTREAM
, false);
2547 && ( !( pOutStreamItem
->GetValue() >>= rOutStream
)
2548 || !pImp
->m_aLogicName
.startsWith("private:stream")) )
2550 pImp
->m_pSet
->ClearItem( SID_OUTPUTSTREAM
);
2551 OSL_FAIL( "Unexpected Output stream parameter!\n" );
2554 if (!pImp
->m_aLogicName
.isEmpty())
2556 // if the logic name is set it should be set in MediaDescriptor as well
2557 SFX_ITEMSET_ARG( pImp
->m_pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, false );
2558 if ( !pFileNameItem
)
2560 // let the ItemSet be created if necessary
2563 SID_FILE_NAME
, INetURLObject( pImp
->m_aLogicName
).GetMainURL( INetURLObject::NO_DECODE
) ) );
2570 //------------------------------------------------------------------
2571 SfxMedium::SfxMedium() : pImp(new SfxMedium_Impl(this))
2576 //------------------------------------------------------------------
2578 void SfxMedium::UseInteractionHandler( sal_Bool bUse
)
2580 pImp
->bAllowDefaultIntHdl
= bUse
;
2583 //------------------------------------------------------------------
2585 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>
2586 SfxMedium::GetInteractionHandler()
2588 // if interaction isnt allowed explicitly ... return empty reference!
2589 if ( !pImp
->bUseInteractionHandler
)
2590 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2592 // search a possible existing handler inside cached item set
2595 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
> xHandler
;
2596 SFX_ITEMSET_ARG( pImp
->m_pSet
, pHandler
, SfxUnoAnyItem
, SID_INTERACTIONHANDLER
, false);
2597 if ( pHandler
&& (pHandler
->GetValue() >>= xHandler
) && xHandler
.is() )
2601 // if default interaction isnt allowed explicitly ... return empty reference!
2602 if ( !pImp
->bAllowDefaultIntHdl
)
2603 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2605 // otherwise return cached default handler ... if it exist.
2606 if ( pImp
->xInteraction
.is() )
2607 return pImp
->xInteraction
;
2609 // create default handler and cache it!
2610 Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2611 pImp
->xInteraction
.set(
2612 task::InteractionHandler::createWithParent(xContext
, 0), UNO_QUERY_THROW
);
2613 return pImp
->xInteraction
;
2616 //----------------------------------------------------------------
2618 void SfxMedium::SetFilter( const SfxFilter
* pFilterP
, sal_Bool
/*bResetOrig*/ )
2620 pImp
->m_pFilter
= pFilterP
;
2623 const SfxFilter
* SfxMedium::GetFilter() const
2625 return pImp
->m_pFilter
;
2628 //----------------------------------------------------------------
2630 const SfxFilter
* SfxMedium::GetOrigFilter( sal_Bool bNotCurrent
) const
2632 return ( pImp
->pOrigFilter
|| bNotCurrent
) ? pImp
->pOrigFilter
: pImp
->m_pFilter
;
2635 //----------------------------------------------------------------
2637 sal_uInt32
SfxMedium::CreatePasswordToModifyHash( const OUString
& aPasswd
, sal_Bool bWriter
)
2639 sal_uInt32 nHash
= 0;
2641 if ( !aPasswd
.isEmpty() )
2645 nHash
= ::comphelper::DocPasswordHelper::GetWordHashAsUINT32( aPasswd
);
2649 rtl_TextEncoding nEncoding
= osl_getThreadTextEncoding();
2650 nHash
= ::comphelper::DocPasswordHelper::GetXLHashAsUINT16( aPasswd
, nEncoding
);
2657 //------------------------------------------------------------------
2659 void SfxMedium::Close()
2661 if ( pImp
->xStorage
.is() )
2666 CloseStreams_Impl();
2668 UnlockFile( false );
2671 void SfxMedium::CloseAndRelease()
2673 if ( pImp
->xStorage
.is() )
2678 CloseAndReleaseStreams_Impl();
2683 void SfxMedium::UnlockFile( sal_Bool bReleaseLockStream
)
2685 #if !HAVE_FEATURE_MULTIUSER_ENVIRONMENT
2686 (void) bReleaseLockStream
;
2688 if ( pImp
->m_xLockingStream
.is() )
2690 if ( bReleaseLockStream
)
2694 uno::Reference
< io::XInputStream
> xInStream
= pImp
->m_xLockingStream
->getInputStream();
2695 uno::Reference
< io::XOutputStream
> xOutStream
= pImp
->m_xLockingStream
->getOutputStream();
2696 if ( xInStream
.is() )
2697 xInStream
->closeInput();
2698 if ( xOutStream
.is() )
2699 xOutStream
->closeOutput();
2701 catch( const uno::Exception
& )
2705 pImp
->m_xLockingStream
.clear();
2708 if ( pImp
->m_bLocked
)
2712 pImp
->m_bLocked
= false;
2713 ::svt::DocumentLockFile
aLockFile( pImp
->m_aLogicName
);
2714 // TODO/LATER: A warning could be shown in case the file is not the own one
2715 aLockFile
.RemoveFile();
2717 catch( const uno::Exception
& )
2723 void SfxMedium::CloseAndReleaseStreams_Impl()
2725 CloseZipStorage_Impl();
2727 uno::Reference
< io::XInputStream
> xInToClose
= pImp
->xInputStream
;
2728 uno::Reference
< io::XOutputStream
> xOutToClose
;
2729 if ( pImp
->xStream
.is() )
2731 xOutToClose
= pImp
->xStream
->getOutputStream();
2733 // if the locking stream is closed here the related member should be cleaned
2734 if ( pImp
->xStream
== pImp
->m_xLockingStream
)
2735 pImp
->m_xLockingStream
.clear();
2738 // The probably exsisting SvStream wrappers should be closed first
2739 CloseStreams_Impl();
2741 // in case of salvage mode the storage is based on the streams
2742 if ( !pImp
->m_bSalvageMode
)
2746 if ( xInToClose
.is() )
2747 xInToClose
->closeInput();
2748 if ( xOutToClose
.is() )
2749 xOutToClose
->closeOutput();
2751 catch ( const uno::Exception
& )
2757 //------------------------------------------------------------------
2758 void SfxMedium::CloseStreams_Impl()
2760 CloseInStream_Impl();
2761 CloseOutStream_Impl();
2764 pImp
->m_pSet
->ClearItem( SID_CONTENT
);
2766 pImp
->aContent
= ::ucbhelper::Content();
2769 //------------------------------------------------------------------
2771 void SfxMedium::SetIsRemote_Impl()
2773 INetURLObject
aObj( GetName() );
2774 switch( aObj
.GetProtocol() )
2777 case INET_PROT_HTTP
:
2778 case INET_PROT_HTTPS
:
2779 case INET_PROT_POP3
:
2780 case INET_PROT_NEWS
:
2781 case INET_PROT_IMAP
:
2783 pImp
->m_bRemote
= true;
2786 pImp
->m_bRemote
= GetName().startsWith("private:msgid");
2790 // As files that are written to the remote transmission must also be able
2792 if (pImp
->m_bRemote
)
2793 pImp
->m_nStorOpenMode
|= STREAM_READ
;
2798 void SfxMedium::SetName( const String
& aNameP
, sal_Bool bSetOrigURL
)
2800 if (pImp
->aOrigURL
.isEmpty())
2801 pImp
->aOrigURL
= pImp
->m_aLogicName
;
2803 pImp
->aOrigURL
= aNameP
;
2804 pImp
->m_aLogicName
= aNameP
;
2805 DELETEZ( pImp
->m_pURLObj
);
2806 pImp
->aContent
= ::ucbhelper::Content();
2810 //----------------------------------------------------------------
2811 const OUString
& SfxMedium::GetOrigURL() const
2813 return pImp
->aOrigURL
.isEmpty() ? pImp
->m_aLogicName
: pImp
->aOrigURL
;
2816 //----------------------------------------------------------------
2818 void SfxMedium::SetPhysicalName_Impl( const OUString
& rNameP
)
2820 if ( rNameP
!= pImp
->m_aName
)
2822 if( pImp
->pTempFile
)
2824 delete pImp
->pTempFile
;
2825 pImp
->pTempFile
= NULL
;
2828 if ( !pImp
->m_aName
.isEmpty() || !rNameP
.isEmpty() )
2829 pImp
->aContent
= ::ucbhelper::Content();
2831 pImp
->m_aName
= rNameP
;
2832 pImp
->m_bTriedStorage
= false;
2833 pImp
->bIsStorage
= false;
2837 //------------------------------------------------------------------
2839 void SfxMedium::ReOpen()
2841 bool bUseInteractionHandler
= pImp
->bUseInteractionHandler
;
2842 pImp
->bUseInteractionHandler
= false;
2844 pImp
->bUseInteractionHandler
= bUseInteractionHandler
;
2847 //------------------------------------------------------------------
2849 void SfxMedium::CompleteReOpen()
2851 // do not use temporary file for reopen and in case of success throw the temporary file away
2852 bool bUseInteractionHandler
= pImp
->bUseInteractionHandler
;
2853 pImp
->bUseInteractionHandler
= false;
2855 ::utl::TempFile
* pTmpFile
= NULL
;
2856 if ( pImp
->pTempFile
)
2858 pTmpFile
= pImp
->pTempFile
;
2859 pImp
->pTempFile
= NULL
;
2860 pImp
->m_aName
= OUString();
2867 if ( pImp
->pTempFile
)
2869 pImp
->pTempFile
->EnableKillingFile( true );
2870 delete pImp
->pTempFile
;
2872 pImp
->pTempFile
= pTmpFile
;
2873 if ( pImp
->pTempFile
)
2874 pImp
->m_aName
= pImp
->pTempFile
->GetFileName();
2878 pTmpFile
->EnableKillingFile( true );
2883 pImp
->bUseInteractionHandler
= bUseInteractionHandler
;
2886 SfxMedium::SfxMedium(const String
&rName
, StreamMode nOpenMode
, const SfxFilter
*pFlt
, SfxItemSet
*pInSet
) :
2887 pImp(new SfxMedium_Impl(this))
2889 pImp
->m_pSet
= pInSet
;
2890 pImp
->m_pFilter
= pFlt
;
2891 pImp
->m_aLogicName
= rName
;
2892 pImp
->m_nStorOpenMode
= nOpenMode
;
2896 SfxMedium::SfxMedium( const uno::Sequence
<beans::PropertyValue
>& aArgs
) :
2897 pImp(new SfxMedium_Impl(this))
2899 SfxAllItemSet
*pParams
= new SfxAllItemSet( SFX_APP()->GetPool() );
2900 pImp
->m_pSet
= pParams
;
2901 TransformParameters( SID_OPENDOC
, aArgs
, *pParams
);
2903 OUString aFilterProvider
, aFilterName
;
2905 const SfxPoolItem
* pItem
= NULL
;
2906 if (pImp
->m_pSet
->HasItem(SID_FILTER_PROVIDER
, &pItem
))
2907 aFilterProvider
= static_cast<const SfxStringItem
*>(pItem
)->GetValue();
2909 if (pImp
->m_pSet
->HasItem(SID_FILTER_NAME
, &pItem
))
2910 aFilterName
= static_cast<const SfxStringItem
*>(pItem
)->GetValue();
2913 if (aFilterProvider
.isEmpty())
2915 // This is a conventional filter type.
2916 pImp
->m_pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4FilterName( aFilterName
);
2920 // This filter is from an external provider such as orcus.
2921 pImp
->m_pCustomFilter
.reset(new SfxFilter(aFilterProvider
, aFilterName
));
2922 pImp
->m_pFilter
= pImp
->m_pCustomFilter
.get();
2925 SFX_ITEMSET_ARG( pImp
->m_pSet
, pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, false );
2928 // QUESTION: there is some treatment of Salvage in Init_Impl; align!
2929 if ( !pSalvageItem
->GetValue().isEmpty() )
2931 // if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
2932 // that must be copied here
2934 SFX_ITEMSET_ARG( pImp
->m_pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, false );
2935 if (!pFileNameItem
) throw uno::RuntimeException();
2936 OUString aNewTempFileURL
= SfxMedium::CreateTempCopyWithExt( pFileNameItem
->GetValue() );
2937 if ( !aNewTempFileURL
.isEmpty() )
2939 pImp
->m_pSet
->Put( SfxStringItem( SID_FILE_NAME
, aNewTempFileURL
) );
2940 pImp
->m_pSet
->ClearItem( SID_INPUTSTREAM
);
2941 pImp
->m_pSet
->ClearItem( SID_STREAM
);
2942 pImp
->m_pSet
->ClearItem( SID_CONTENT
);
2946 OSL_FAIL( "Can not create a new temporary file for crash recovery!\n" );
2951 SFX_ITEMSET_ARG( pImp
->m_pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, false );
2952 if ( pReadOnlyItem
&& pReadOnlyItem
->GetValue() )
2953 pImp
->m_bOriginallyReadOnly
= true;
2955 SFX_ITEMSET_ARG( pImp
->m_pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, false );
2956 if (!pFileNameItem
) throw uno::RuntimeException();
2957 pImp
->m_aLogicName
= pFileNameItem
->GetValue();
2958 pImp
->m_nStorOpenMode
= pImp
->m_bOriginallyReadOnly
? SFX_STREAM_READONLY
: SFX_STREAM_READWRITE
;
2963 //------------------------------------------------------------------
2965 SfxMedium::SfxMedium( const uno::Reference
< embed::XStorage
>& rStor
, const String
& rBaseURL
, const SfxItemSet
* p
) :
2966 pImp(new SfxMedium_Impl(this))
2968 OUString aType
= SfxFilter::GetTypeFromStorage(rStor
);
2969 pImp
->m_pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4EA( aType
);
2970 DBG_ASSERT( pImp
->m_pFilter
, "No Filter for storage found!" );
2973 pImp
->xStorage
= rStor
;
2974 pImp
->bDisposeStorage
= false;
2976 // always take BaseURL first, could be overwritten by ItemSet
2977 GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, rBaseURL
) );
2979 GetItemSet()->Put( *p
);
2982 //------------------------------------------------------------------
2984 SfxMedium::SfxMedium( const uno::Reference
< embed::XStorage
>& rStor
, const String
& rBaseURL
, const String
&rTypeName
, const SfxItemSet
* p
) :
2985 pImp(new SfxMedium_Impl(this))
2987 pImp
->m_pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4EA( rTypeName
);
2988 DBG_ASSERT( pImp
->m_pFilter
, "No Filter for storage found!" );
2991 pImp
->xStorage
= rStor
;
2992 pImp
->bDisposeStorage
= false;
2994 // always take BaseURL first, could be overwritten by ItemSet
2995 GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, rBaseURL
) );
2997 GetItemSet()->Put( *p
);
3000 //------------------------------------------------------------------
3002 SfxMedium::~SfxMedium()
3004 // if there is a requirement to clean the backup this is the last possibility to do it
3009 if( pImp
->bIsTemp
&& !pImp
->m_aName
.isEmpty() )
3012 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp
->m_aName
, aTemp
))
3014 OSL_FAIL("Physical name not convertible!");
3017 if ( !::utl::UCBContentHelper::Kill( aTemp
) )
3019 OSL_FAIL("Couldn't remove temporary file!");
3026 const OUString
& SfxMedium::GetName() const
3028 return pImp
->m_aLogicName
;
3031 const INetURLObject
& SfxMedium::GetURLObject() const
3033 if (!pImp
->m_pURLObj
)
3035 pImp
->m_pURLObj
= new INetURLObject( pImp
->m_aLogicName
);
3036 if (pImp
->m_pURLObj
->HasMark())
3037 *pImp
->m_pURLObj
= INetURLObject( pImp
->m_aLogicName
).GetURLNoMark();
3040 return *pImp
->m_pURLObj
;
3043 void SfxMedium::SetExpired_Impl( const DateTime
& rDateTime
)
3045 pImp
->aExpireTime
= rDateTime
;
3047 //----------------------------------------------------------------
3049 sal_Bool
SfxMedium::IsExpired() const
3051 return pImp
->aExpireTime
.IsValidAndGregorian() && pImp
->aExpireTime
< DateTime( DateTime::SYSTEM
);
3053 //----------------------------------------------------------------
3055 void SfxMedium::ForceSynchronStream_Impl( sal_Bool bForce
)
3057 if( pImp
->m_pInStream
)
3059 SvLockBytes
* pBytes
= pImp
->m_pInStream
->GetLockBytes();
3061 pBytes
->SetSynchronMode( bForce
);
3065 //----------------------------------------------------------------
3066 SfxFrame
* SfxMedium::GetLoadTargetFrame() const
3068 return pImp
->wLoadTargetFrame
;
3071 void SfxMedium::setStreamToLoadFrom(const com::sun::star::uno::Reference
<com::sun::star::io::XInputStream
>& xInputStream
,sal_Bool bIsReadOnly
)
3073 pImp
->m_xInputStreamToLoadFrom
= xInputStream
;
3074 pImp
->m_bInputStreamIsReadOnly
= bIsReadOnly
;
3077 void SfxMedium::SetLoadTargetFrame(SfxFrame
* pFrame
)
3079 pImp
->wLoadTargetFrame
= pFrame
;
3081 //----------------------------------------------------------------
3083 void SfxMedium::SetStorage_Impl( const uno::Reference
< embed::XStorage
>& rStor
)
3085 pImp
->xStorage
= rStor
;
3087 //----------------------------------------------------------------
3089 SfxItemSet
* SfxMedium::GetItemSet() const
3091 // this method *must* return an ItemSet, returning NULL can cause crashes
3093 pImp
->m_pSet
= new SfxAllItemSet( SFX_APP()->GetPool() );
3094 return pImp
->m_pSet
;
3096 //----------------------------------------------------------------
3098 SvKeyValueIterator
* SfxMedium::GetHeaderAttributes_Impl()
3100 if( !pImp
->xAttributes
.Is() )
3102 pImp
->xAttributes
= SvKeyValueIteratorRef( new SvKeyValueIterator
);
3104 if ( GetContent().is() )
3108 Any aAny
= pImp
->aContent
.getPropertyValue( OUString("MediaType") );
3109 OUString aContentType
;
3110 aAny
>>= aContentType
;
3112 pImp
->xAttributes
->Append( SvKeyValue( OUString("content-type"), aContentType
) );
3114 catch ( const ::com::sun::star::uno::Exception
& )
3120 return pImp
->xAttributes
;
3123 ::com::sun::star::uno::Reference
< ::com::sun::star::io::XInputStream
> SfxMedium::GetInputStream()
3125 if ( !pImp
->xInputStream
.is() )
3127 return pImp
->xInputStream
;
3130 const uno::Sequence
< util::RevisionTag
>& SfxMedium::GetVersionList( bool _bNoReload
)
3132 // if the medium has no name, then this medium should represent a new document and can have no version info
3133 if ( ( !_bNoReload
|| !pImp
->m_bVersionsAlreadyLoaded
) && !pImp
->aVersions
.getLength() &&
3134 ( !pImp
->m_aName
.isEmpty() || !pImp
->m_aLogicName
.isEmpty() ) && GetStorage().is() )
3136 uno::Reference
< document::XDocumentRevisionListPersistence
> xReader
=
3137 document::DocumentRevisionListPersistence::create( comphelper::getProcessComponentContext() );
3140 pImp
->aVersions
= xReader
->load( GetStorage() );
3142 catch ( const uno::Exception
& )
3147 if ( !pImp
->m_bVersionsAlreadyLoaded
)
3148 pImp
->m_bVersionsAlreadyLoaded
= true;
3150 return pImp
->aVersions
;
3153 uno::Sequence
< util::RevisionTag
> SfxMedium::GetVersionList( const uno::Reference
< embed::XStorage
>& xStorage
)
3155 uno::Reference
< document::XDocumentRevisionListPersistence
> xReader
=
3156 document::DocumentRevisionListPersistence::create( comphelper::getProcessComponentContext() );
3159 return xReader
->load( xStorage
);
3161 catch ( const uno::Exception
& )
3165 return uno::Sequence
< util::RevisionTag
>();
3168 sal_uInt16
SfxMedium::AddVersion_Impl( util::RevisionTag
& rRevision
)
3170 if ( GetStorage().is() )
3172 // To determine a unique name for the stream
3173 std::vector
<sal_uInt32
> aLongs
;
3174 sal_Int32 nLength
= pImp
->aVersions
.getLength();
3175 for ( sal_Int32 m
=0; m
<nLength
; m
++ )
3177 sal_uInt32 nVer
= static_cast<sal_uInt32
>(String( pImp
->aVersions
[m
].Identifier
).Copy(7).ToInt32());
3179 for ( n
=0; n
<aLongs
.size(); ++n
)
3180 if ( nVer
<aLongs
[n
] )
3183 aLongs
.insert( aLongs
.begin()+n
, nVer
);
3187 for ( nKey
=0; nKey
<aLongs
.size(); ++nKey
)
3188 if ( aLongs
[nKey
] > ( sal_uIntPtr
) nKey
+1 )
3191 OUString aRevName
= "Version" + OUString::number( nKey
+ 1 );
3192 pImp
->aVersions
.realloc( nLength
+1 );
3193 rRevision
.Identifier
= aRevName
;
3194 pImp
->aVersions
[nLength
] = rRevision
;
3201 sal_Bool
SfxMedium::RemoveVersion_Impl( const OUString
& rName
)
3203 if ( !pImp
->aVersions
.getLength() )
3206 sal_Int32 nLength
= pImp
->aVersions
.getLength();
3207 for ( sal_Int32 n
=0; n
<nLength
; n
++ )
3209 if ( pImp
->aVersions
[n
].Identifier
== rName
)
3211 for ( sal_Int32 m
=n
; m
<nLength
-1; m
++ )
3212 pImp
->aVersions
[m
] = pImp
->aVersions
[m
+1];
3213 pImp
->aVersions
.realloc(nLength
-1);
3221 sal_Bool
SfxMedium::TransferVersionList_Impl( SfxMedium
& rMedium
)
3223 if ( rMedium
.pImp
->aVersions
.getLength() )
3225 pImp
->aVersions
= rMedium
.pImp
->aVersions
;
3232 sal_Bool
SfxMedium::SaveVersionList_Impl( sal_Bool
/*bUseXML*/ )
3234 if ( GetStorage().is() )
3236 if ( !pImp
->aVersions
.getLength() )
3239 uno::Reference
< document::XDocumentRevisionListPersistence
> xWriter
=
3240 document::DocumentRevisionListPersistence::create( comphelper::getProcessComponentContext() );
3243 xWriter
->store( GetStorage(), pImp
->aVersions
);
3246 catch ( const uno::Exception
& )
3254 //----------------------------------------------------------------
3255 sal_Bool
SfxMedium::IsReadOnly()
3257 // a) ReadOnly filter cant produce read/write contents!
3259 (pImp
->m_pFilter
) &&
3260 ((pImp
->m_pFilter
->GetFilterFlags() & SFX_FILTER_OPENREADONLY
) == SFX_FILTER_OPENREADONLY
)
3263 // b) if filter allow read/write contents .. check open mode of the storage
3265 bReadOnly
= !( GetOpenMode() & STREAM_WRITE
);
3267 // c) the API can force the readonly state!
3270 SFX_ITEMSET_ARG( GetItemSet(), pItem
, SfxBoolItem
, SID_DOC_READONLY
, false);
3272 bReadOnly
= pItem
->GetValue();
3278 bool SfxMedium::IsOriginallyReadOnly() const
3280 return pImp
->m_bOriginallyReadOnly
;
3283 //----------------------------------------------------------------
3284 sal_Bool
SfxMedium::SetWritableForUserOnly( const OUString
& aURL
)
3286 // UCB does not allow to allow write access only for the user,
3288 bool bResult
= false;
3290 ::osl::DirectoryItem aDirItem
;
3291 if ( ::osl::DirectoryItem::get( aURL
, aDirItem
) == ::osl::FileBase::E_None
)
3293 ::osl::FileStatus
aFileStatus( osl_FileStatus_Mask_Attributes
);
3294 if ( aDirItem
.getFileStatus( aFileStatus
) == osl::FileBase::E_None
3295 && aFileStatus
.isValid( osl_FileStatus_Mask_Attributes
) )
3297 sal_uInt64 nAttributes
= aFileStatus
.getAttributes();
3299 nAttributes
&= ~(osl_File_Attribute_OwnWrite
|
3300 osl_File_Attribute_GrpWrite
|
3301 osl_File_Attribute_OthWrite
|
3302 osl_File_Attribute_ReadOnly
);
3303 nAttributes
|= (osl_File_Attribute_OwnWrite
|
3304 osl_File_Attribute_OwnRead
);
3306 bResult
= ( osl::File::setAttributes( aURL
, nAttributes
) == ::osl::FileBase::E_None
);
3313 //----------------------------------------------------------------
3314 void SfxMedium::CreateTempFile( sal_Bool bReplace
)
3316 if ( pImp
->pTempFile
)
3321 DELETEZ( pImp
->pTempFile
);
3322 pImp
->m_aName
= OUString();
3325 pImp
->pTempFile
= new ::utl::TempFile();
3326 pImp
->pTempFile
->EnableKillingFile( true );
3327 pImp
->m_aName
= pImp
->pTempFile
->GetFileName();
3328 OUString aTmpURL
= pImp
->pTempFile
->GetURL();
3329 if ( pImp
->m_aName
.isEmpty() || aTmpURL
.isEmpty() )
3331 SetError( ERRCODE_IO_CANTWRITE
, OUString( OSL_LOG_PREFIX
) );
3335 if ( !(pImp
->m_nStorOpenMode
& STREAM_TRUNC
) )
3337 bool bTransferSuccess
= false;
3339 if ( GetContent().is()
3340 && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
3341 && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
3343 // if there is already such a document, we should copy it
3344 // if it is a file system use OS copy process
3347 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
3348 INetURLObject
aTmpURLObj( aTmpURL
);
3349 OUString aFileName
= aTmpURLObj
.getName( INetURLObject::LAST_SEGMENT
,
3351 INetURLObject::DECODE_WITH_CHARSET
);
3352 if ( !aFileName
.isEmpty() && aTmpURLObj
.removeSegment() )
3354 ::ucbhelper::Content
aTargetContent( aTmpURLObj
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
, comphelper::getProcessComponentContext() );
3355 OUString sMimeType
= pImp
->getFilterMimeType();
3356 if ( aTargetContent
.transferContent( pImp
->aContent
, ::ucbhelper::InsertOperation_COPY
, aFileName
, NameClash::OVERWRITE
, sMimeType
) )
3358 SetWritableForUserOnly( aTmpURL
);
3359 bTransferSuccess
= true;
3363 catch( const uno::Exception
& )
3366 if ( bTransferSuccess
)
3373 if ( !bTransferSuccess
&& pImp
->m_pInStream
)
3375 // the case when there is no URL-access available or this is a remote protocoll
3376 // but there is an input stream
3378 if ( pImp
->m_pOutStream
)
3380 char *pBuf
= new char [8192];
3381 sal_uInt32 nErr
= ERRCODE_NONE
;
3383 pImp
->m_pInStream
->Seek(0);
3384 pImp
->m_pOutStream
->Seek(0);
3386 while( !pImp
->m_pInStream
->IsEof() && nErr
== ERRCODE_NONE
)
3388 sal_uInt32 nRead
= pImp
->m_pInStream
->Read( pBuf
, 8192 );
3389 nErr
= pImp
->m_pInStream
->GetError();
3390 pImp
->m_pOutStream
->Write( pBuf
, nRead
);
3393 bTransferSuccess
= true;
3397 CloseOutStream_Impl();
3401 // Quite strange design, but currently it is expected that in this case no transfer happens
3402 // TODO/LATER: get rid of this inconsistent part of the call design
3403 bTransferSuccess
= true;
3407 if ( !bTransferSuccess
)
3409 SetError( ERRCODE_IO_CANTWRITE
, OUString( OSL_LOG_PREFIX
) );
3417 //----------------------------------------------------------------
3418 void SfxMedium::CreateTempFileNoCopy()
3420 // this call always replaces the existing temporary file
3421 if ( pImp
->pTempFile
)
3422 delete pImp
->pTempFile
;
3424 pImp
->pTempFile
= new ::utl::TempFile();
3425 pImp
->pTempFile
->EnableKillingFile( true );
3426 pImp
->m_aName
= pImp
->pTempFile
->GetFileName();
3427 if ( pImp
->m_aName
.isEmpty() )
3429 SetError( ERRCODE_IO_CANTWRITE
, OUString( OSL_LOG_PREFIX
) );
3433 CloseOutStream_Impl();
3437 sal_Bool
SfxMedium::SignContents_Impl( sal_Bool bScriptingContent
, const OUString
& aODFVersion
, sal_Bool bHasValidDocumentSignature
)
3439 bool bChanges
= false;
3441 // the medium should be closed to be able to sign, the caller is responsible to close it
3442 if ( !IsOpen() && !GetError() )
3444 // The component should know if there was a valid document signature, since
3445 // it should show a warning in this case
3446 uno::Reference
< security::XDocumentDigitalSignatures
> xSigner(
3447 security::DocumentDigitalSignatures::createWithVersionAndValidSignature(
3448 comphelper::getProcessComponentContext(), aODFVersion
, bHasValidDocumentSignature
) );
3450 uno::Reference
< embed::XStorage
> xWriteableZipStor
;
3451 if ( !IsReadOnly() )
3453 // we can reuse the temporary file if there is one already
3454 CreateTempFile( false );
3459 if ( !pImp
->xStream
.is() )
3460 throw uno::RuntimeException();
3462 xWriteableZipStor
= ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xStream
);
3463 if ( !xWriteableZipStor
.is() )
3464 throw uno::RuntimeException();
3466 uno::Reference
< embed::XStorage
> xMetaInf
= xWriteableZipStor
->openStorageElement(
3467 OUString( "META-INF" ),
3468 embed::ElementModes::READWRITE
);
3469 if ( !xMetaInf
.is() )
3470 throw uno::RuntimeException();
3472 if ( bScriptingContent
)
3474 // If the signature has already the document signature it will be removed
3475 // after the scripting signature is inserted.
3476 uno::Reference
< io::XStream
> xStream(
3477 xMetaInf
->openStreamElement( xSigner
->getScriptingContentSignatureDefaultStreamName(),
3478 embed::ElementModes::READWRITE
),
3479 uno::UNO_SET_THROW
);
3481 if ( xSigner
->signScriptingContent( GetZipStorageToSign_Impl(), xStream
) )
3483 // remove the document signature if any
3484 OUString aDocSigName
= xSigner
->getDocumentContentSignatureDefaultStreamName();
3485 if ( !aDocSigName
.isEmpty() && xMetaInf
->hasByName( aDocSigName
) )
3486 xMetaInf
->removeElement( aDocSigName
);
3488 uno::Reference
< embed::XTransactedObject
> xTransact( xMetaInf
, uno::UNO_QUERY_THROW
);
3489 xTransact
->commit();
3490 xTransact
.set( xWriteableZipStor
, uno::UNO_QUERY_THROW
);
3491 xTransact
->commit();
3493 // the temporary file has been written, commit it to the original file
3500 uno::Reference
< io::XStream
> xStream(
3501 xMetaInf
->openStreamElement( xSigner
->getDocumentContentSignatureDefaultStreamName(),
3502 embed::ElementModes::READWRITE
),
3503 uno::UNO_SET_THROW
);
3505 if ( xSigner
->signDocumentContent( GetZipStorageToSign_Impl(), xStream
) )
3507 uno::Reference
< embed::XTransactedObject
> xTransact( xMetaInf
, uno::UNO_QUERY_THROW
);
3508 xTransact
->commit();
3509 xTransact
.set( xWriteableZipStor
, uno::UNO_QUERY_THROW
);
3510 xTransact
->commit();
3512 // the temporary file has been written, commit it to the original file
3518 catch ( const uno::Exception
& )
3520 OSL_FAIL( "Couldn't use signing functionality!\n" );
3529 if ( bScriptingContent
)
3530 xSigner
->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference
< io::XInputStream
>() );
3532 xSigner
->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference
< io::XInputStream
>() );
3534 catch( const uno::Exception
& )
3536 OSL_FAIL( "Couldn't use signing functionality!\n" );
3546 //----------------------------------------------------------------
3547 sal_uInt16
SfxMedium::GetCachedSignatureState_Impl()
3549 return pImp
->m_nSignatureState
;
3552 //----------------------------------------------------------------
3553 void SfxMedium::SetCachedSignatureState_Impl( sal_uInt16 nState
)
3555 pImp
->m_nSignatureState
= nState
;
3558 sal_Bool
SfxMedium::HasStorage_Impl() const
3560 return pImp
->xStorage
.is();
3563 sal_Bool
SfxMedium::IsOpen() const
3565 return pImp
->m_pInStream
|| pImp
->m_pOutStream
|| pImp
->xStorage
.is();
3568 OUString
SfxMedium::CreateTempCopyWithExt( const OUString
& aURL
)
3572 if ( !aURL
.isEmpty() )
3574 sal_Int32 nPrefixLen
= aURL
.lastIndexOf( '.' );
3575 String aExt
= ( nPrefixLen
== -1 ) ? String() : String( aURL
.copy( nPrefixLen
) );
3577 OUString aNewTempFileURL
= ::utl::TempFile( String(), &aExt
).GetURL();
3578 if ( !aNewTempFileURL
.isEmpty() )
3580 INetURLObject
aSource( aURL
);
3581 INetURLObject
aDest( aNewTempFileURL
);
3582 OUString aFileName
= aDest
.getName( INetURLObject::LAST_SEGMENT
,
3584 INetURLObject::DECODE_WITH_CHARSET
);
3585 if ( !aFileName
.isEmpty() && aDest
.removeSegment() )
3589 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
3590 ::ucbhelper::Content
aTargetContent( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
, comphelper::getProcessComponentContext() );
3591 ::ucbhelper::Content
aSourceContent( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
, comphelper::getProcessComponentContext() );
3592 if ( aTargetContent
.transferContent( aSourceContent
,
3593 ::ucbhelper::InsertOperation_COPY
,
3595 NameClash::OVERWRITE
) )
3598 aResult
= aNewTempFileURL
;
3601 catch( const uno::Exception
& )
3610 sal_Bool
SfxMedium::CallApproveHandler( const uno::Reference
< task::XInteractionHandler
>& xHandler
, uno::Any aRequest
, sal_Bool bAllowAbort
)
3612 bool bResult
= false;
3614 if ( xHandler
.is() )
3618 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( bAllowAbort
? 2 : 1 );
3620 ::rtl::Reference
< ::comphelper::OInteractionApprove
> pApprove( new ::comphelper::OInteractionApprove
);
3621 aContinuations
[ 0 ] = pApprove
.get();
3625 ::rtl::Reference
< ::comphelper::OInteractionAbort
> pAbort( new ::comphelper::OInteractionAbort
);
3626 aContinuations
[ 1 ] = pAbort
.get();
3629 xHandler
->handle(::framework::InteractionRequest::CreateRequest (aRequest
,aContinuations
));
3630 bResult
= pApprove
->wasSelected();
3632 catch( const Exception
& )
3640 OUString
SfxMedium::SwitchDocumentToTempFile()
3642 // the method returns empty string in case of failure
3644 OUString aOrigURL
= pImp
->m_aLogicName
;
3646 if ( !aOrigURL
.isEmpty() )
3648 sal_Int32 nPrefixLen
= aOrigURL
.lastIndexOf( '.' );
3649 String aExt
= ( nPrefixLen
== -1 ) ? String() : String( aOrigURL
.copy( nPrefixLen
) );
3650 OUString aNewURL
= ::utl::TempFile( String(), &aExt
).GetURL();
3652 // TODO/LATER: In future the aLogicName should be set to shared folder URL
3653 // and a temporary file should be created. Transport_Impl should be impossible then.
3654 if ( !aNewURL
.isEmpty() )
3656 uno::Reference
< embed::XStorage
> xStorage
= GetStorage();
3657 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY
);
3659 if ( xOptStorage
.is() )
3661 // TODO/LATER: reuse the pImp->pTempFile if it already exists
3662 CanDisposeStorage_Impl( false );
3664 SetPhysicalName_Impl( String() );
3667 // remove the readonly state
3668 bool bWasReadonly
= false;
3669 pImp
->m_nStorOpenMode
= SFX_STREAM_READWRITE
;
3670 SFX_ITEMSET_ARG( pImp
->m_pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, false );
3671 if ( pReadOnlyItem
&& pReadOnlyItem
->GetValue() )
3672 bWasReadonly
= true;
3673 GetItemSet()->ClearItem( SID_DOC_READONLY
);
3676 LockOrigFileOnDemand( false, false );
3677 CreateTempFile( true );
3680 if ( pImp
->xStream
.is() )
3684 xOptStorage
->writeAndAttachToStream( pImp
->xStream
);
3685 pImp
->xStorage
= xStorage
;
3688 catch( const uno::Exception
& )
3692 if ( aResult
.isEmpty() )
3695 SetPhysicalName_Impl( String() );
3696 SetName( aOrigURL
);
3699 // set the readonly state back
3700 pImp
->m_nStorOpenMode
= SFX_STREAM_READONLY
;
3701 GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY
, true));
3704 pImp
->xStorage
= xStorage
;
3713 sal_Bool
SfxMedium::SwitchDocumentToFile( const OUString
& aURL
)
3715 // the method is only for storage based documents
3716 bool bResult
= false;
3717 OUString aOrigURL
= pImp
->m_aLogicName
;
3719 if ( !aURL
.isEmpty() && !aOrigURL
.isEmpty() )
3721 uno::Reference
< embed::XStorage
> xStorage
= GetStorage();
3722 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY
);
3724 if ( xOptStorage
.is() )
3726 // TODO/LATER: reuse the pImp->pTempFile if it already exists
3727 CanDisposeStorage_Impl( false );
3729 SetPhysicalName_Impl( String() );
3732 // open the temporary file based document
3734 LockOrigFileOnDemand( false, false );
3735 CreateTempFile( true );
3738 if ( pImp
->xStream
.is() )
3742 uno::Reference
< io::XTruncate
> xTruncate( pImp
->xStream
, uno::UNO_QUERY_THROW
);
3743 if ( xTruncate
.is() )
3744 xTruncate
->truncate();
3746 xOptStorage
->writeAndAttachToStream( pImp
->xStream
);
3747 pImp
->xStorage
= xStorage
;
3750 catch( const uno::Exception
& )
3757 SetPhysicalName_Impl( String() );
3758 SetName( aOrigURL
);
3760 pImp
->xStorage
= xStorage
;
3768 void SfxMedium::SetInCheckIn( bool bInCheckIn
)
3770 pImp
->m_bInCheckIn
= bInCheckIn
;
3773 bool SfxMedium::IsInCheckIn( )
3775 return pImp
->m_bInCheckIn
;
3778 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */