1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docfile.cxx,v $
10 * $Revision: 1.203.50.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
33 #include <sfx2/docfile.hxx>
34 #include "sfx2/signaturestate.hxx"
36 #include <uno/mapping.hxx>
37 #include <com/sun/star/task/XInteractionHandler.hpp>
38 #include <com/sun/star/uno/Reference.h>
39 #include <com/sun/star/ucb/XContent.hpp>
40 #include <com/sun/star/document/XDocumentRevisionListPersistence.hpp>
41 #include <com/sun/star/document/LockedDocumentRequest.hpp>
42 #include <com/sun/star/document/OwnLockOnDocumentRequest.hpp>
43 #include <com/sun/star/document/LockedOnSavingRequest.hpp>
44 #include <com/sun/star/document/LockFileIgnoreRequest.hpp>
45 #include <com/sun/star/document/ChangedByOthersRequest.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/embed/XTransactedObject.hpp>
48 #include <com/sun/star/embed/ElementModes.hpp>
49 #include <com/sun/star/embed/UseBackupException.hpp>
50 #include <com/sun/star/embed/XOptimizedStorage.hpp>
51 #include <com/sun/star/ucb/InteractiveIOException.hpp>
52 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
53 #include <com/sun/star/ucb/CommandFailedException.hpp>
54 #include <com/sun/star/ucb/CommandAbortedException.hpp>
55 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
56 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
57 #include <com/sun/star/ucb/XContentProvider.hpp>
58 #include <com/sun/star/ucb/XProgressHandler.hpp>
59 #include <com/sun/star/ucb/XCommandInfo.hpp>
60 #include <com/sun/star/util/XArchiver.hpp>
61 #include <com/sun/star/io/XOutputStream.hpp>
62 #include <com/sun/star/io/XInputStream.hpp>
63 #include <com/sun/star/io/XTruncate.hpp>
64 #include <com/sun/star/io/XStreamListener.hpp>
65 #include <com/sun/star/io/XSeekable.hpp>
66 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
67 #include <com/sun/star/lang/XInitialization.hpp>
68 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
69 #include <com/sun/star/ucb/NameClash.hpp>
70 #include <com/sun/star/ucb/TransferInfo.hpp>
71 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
72 #include <com/sun/star/ucb/OpenMode.hpp>
73 #include <com/sun/star/ucb/NameClashException.hpp>
74 #include <com/sun/star/logging/XSimpleLogRing.hpp>
75 #include <cppuhelper/implbase1.hxx>
76 #include <com/sun/star/beans/PropertyValue.hpp>
77 #ifndef _COM_SUN_STAR_SECURITY_DOCUMENTSIGNATURESINFORMATION_HPP_
78 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
80 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
81 #include <tools/zcodec.hxx>
82 #include <tools/cachestr.hxx>
83 #include <tools/urlobj.hxx>
84 #include <unotools/tempfile.hxx>
85 #include <comphelper/processfactory.hxx>
86 #include <comphelper/componentcontext.hxx>
87 #include <framework/interaction.hxx>
88 #include <unotools/streamhelper.hxx>
89 #include <unotools/localedatawrapper.hxx>
90 #ifndef _MSGBOX_HXX //autogen
91 #include <vcl/msgbox.hxx>
93 #include <svtools/stritem.hxx>
94 #include <svtools/eitem.hxx>
95 #include <svtools/lckbitem.hxx>
96 #include <svtools/sfxecode.hxx>
97 #include <svtools/itemset.hxx>
98 #include <svtools/intitem.hxx>
99 #include <svtools/svparser.hxx> // SvKeyValue
100 #include <cppuhelper/weakref.hxx>
101 #include <cppuhelper/implbase1.hxx>
103 #define _SVSTDARR_ULONGS
104 #define _SVSTDARR_STRINGSDTOR
105 #include <svtools/svstdarr.hxx>
107 #include <unotools/streamwrap.hxx>
109 #include <rtl/logfile.hxx>
110 #include <osl/file.hxx>
112 using namespace ::com::sun::star
;
113 using namespace ::com::sun::star::uno
;
114 using namespace ::com::sun::star::ucb
;
115 using namespace ::com::sun::star::beans
;
116 using namespace ::com::sun::star::io
;
118 #include <comphelper/storagehelper.hxx>
119 #include <comphelper/mediadescriptor.hxx>
120 #include <comphelper/configurationhelper.hxx>
121 #include <tools/urlobj.hxx>
122 #include <tools/inetmime.hxx>
123 #include <unotools/ucblockbytes.hxx>
124 #include <svtools/pathoptions.hxx>
125 #include <svtools/asynclink.hxx>
126 #include <svtools/inettype.hxx>
127 #include <ucbhelper/contentbroker.hxx>
128 #include <ucbhelper/commandenvironment.hxx>
129 #include <unotools/localfilehelper.hxx>
130 #include <unotools/ucbstreamhelper.hxx>
131 #include <unotools/ucbhelper.hxx>
132 #include <unotools/progresshandlerwrap.hxx>
133 #include <ucbhelper/content.hxx>
134 #include <ucbhelper/interactionrequest.hxx>
135 #include <sot/stg.hxx>
136 #include <svtools/saveopt.hxx>
137 #include <svtools/documentlockfile.hxx>
139 #include "opostponedtruncationstream.hxx"
140 #include "helper.hxx"
141 #include <sfx2/request.hxx> // SFX_ITEMSET_SET
142 #include <sfx2/app.hxx> // GetFilterMatcher
143 #include <sfx2/frame.hxx> // LoadTargetFrame
144 #include "fltfnc.hxx" // SfxFilterMatcher
145 #include <sfx2/docfilt.hxx> // SfxFilter
146 #include <sfx2/objsh.hxx> // CheckOpenMode
147 #include <sfx2/docfac.hxx> // GetFilterContainer
149 #include "openflag.hxx" // SFX_STREAM_READONLY etc.
150 #include "sfxresid.hxx"
151 #include <sfx2/appuno.hxx>
153 //#include "xmlversion.hxx"
155 #define MAX_REDIRECT 5
158 //==========================================================
161 static const sal_Int8 LOCK_UI_NOLOCK
= 0;
162 static const sal_Int8 LOCK_UI_SUCCEEDED
= 1;
163 static const sal_Int8 LOCK_UI_TRY
= 2;
165 //----------------------------------------------------------------
166 sal_Bool
IsSystemFileLockingUsed()
168 // check whether system file locking has been used, the default value is false
169 sal_Bool bUseSystemLock
= sal_False
;
173 uno::Reference
< uno::XInterface
> xCommonConfig
= ::comphelper::ConfigurationHelper::openConfig(
174 ::comphelper::getProcessServiceFactory(),
175 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
176 ::comphelper::ConfigurationHelper::E_STANDARD
);
177 if ( !xCommonConfig
.is() )
178 throw uno::RuntimeException();
180 ::comphelper::ConfigurationHelper::readRelativeKey(
182 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
183 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentSystemFileLocking" ) ) ) >>= bUseSystemLock
;
185 catch( const uno::Exception
& )
189 return bUseSystemLock
;
192 //----------------------------------------------------------------
193 sal_Bool
IsOOoLockFileUsed()
195 // check whether system file locking has been used, the default value is false
196 sal_Bool bOOoLockFileUsed
= sal_False
;
200 uno::Reference
< uno::XInterface
> xCommonConfig
= ::comphelper::ConfigurationHelper::openConfig(
201 ::comphelper::getProcessServiceFactory(),
202 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
203 ::comphelper::ConfigurationHelper::E_STANDARD
);
204 if ( !xCommonConfig
.is() )
205 throw uno::RuntimeException();
207 ::comphelper::ConfigurationHelper::readRelativeKey(
209 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
210 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentOOoLockFile" ) ) ) >>= bOOoLockFileUsed
;
212 catch( const uno::Exception
& )
216 return bOOoLockFileUsed
;
219 } // anonymous namespace
220 //==========================================================
223 //----------------------------------------------------------------
224 class SfxMediumHandler_Impl
: public ::cppu::WeakImplHelper1
< com::sun::star::task::XInteractionHandler
>
226 com::sun::star::uno::Reference
< com::sun::star::task::XInteractionHandler
> m_xInter
;
229 virtual void SAL_CALL
handle( const com::sun::star::uno::Reference
< com::sun::star::task::XInteractionRequest
>& xRequest
)
230 throw( com::sun::star::uno::RuntimeException
);
232 SfxMediumHandler_Impl( com::sun::star::uno::Reference
< com::sun::star::task::XInteractionHandler
> xInteraction
)
233 : m_xInter( xInteraction
)
236 ~SfxMediumHandler_Impl();
239 //----------------------------------------------------------------
240 SfxMediumHandler_Impl::~SfxMediumHandler_Impl()
244 //----------------------------------------------------------------
245 void SAL_CALL
SfxMediumHandler_Impl::handle( const com::sun::star::uno::Reference
< com::sun::star::task::XInteractionRequest
>& xRequest
)
246 throw( com::sun::star::uno::RuntimeException
)
251 com::sun::star::uno::Any aRequest
= xRequest
->getRequest();
252 com::sun::star::ucb::InteractiveIOException aIoException
;
253 com::sun::star::ucb::UnsupportedDataSinkException aSinkException
;
254 if ( (aRequest
>>= aIoException
) && ( aIoException
.Code
== IOErrorCode_ACCESS_DENIED
|| aIoException
.Code
== IOErrorCode_LOCKING_VIOLATION
) )
257 if ( aRequest
>>= aSinkException
)
260 m_xInter
->handle( xRequest
);
263 //----------------------------------------------------------------
264 class SfxPoolCancelManager_Impl
: public SfxCancelManager
,
265 public SfxCancellable
,
269 SfxCancelManagerWeak wParent
;
271 ~SfxPoolCancelManager_Impl();
273 SfxPoolCancelManager_Impl( SfxCancelManager
* pParent
, const String
& rName
);
275 virtual void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
);
276 using SfxCancelManager::Cancel
;
277 virtual void Cancel();
280 //----------------------------------------------------------------
281 SV_DECL_IMPL_REF( SfxPoolCancelManager_Impl
)
284 //----------------------------------------------------------------
285 SfxPoolCancelManager_Impl::SfxPoolCancelManager_Impl( SfxCancelManager
* pParent
, const String
& rName
)
286 : SfxCancelManager( pParent
),
287 SfxCancellable( pParent
? pParent
: this, rName
),
292 StartListening( *this );
297 //----------------------------------------------------------------
298 SfxPoolCancelManager_Impl::~SfxPoolCancelManager_Impl()
300 for( sal_uInt16 nPos
= GetCancellableCount(); nPos
--; )
302 // nicht an Parent uebernehmen!
303 SfxCancellable
* pCbl
= GetCancellable( nPos
);
305 pCbl
->SetManager( 0 );
310 //----------------------------------------------------------------
311 void SfxPoolCancelManager_Impl::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& /*rHint*/ )
313 if( !GetCancellableCount() ) SetManager( 0 );
314 else if( !GetManager() )
316 if( !wParent
.Is() ) wParent
= SFX_APP()->GetCancelManager();
317 SetManager( wParent
);
321 //----------------------------------------------------------------
322 void SfxPoolCancelManager_Impl::Cancel()
324 SfxPoolCancelManager_ImplRef xThis
= this;
325 for( sal_uInt16 nPos
= GetCancellableCount(); nPos
--; )
327 SfxCancellable
* pCbl
= GetCancellable( nPos
);
328 // Wenn wir nicht im Button stehen
329 if( pCbl
&& pCbl
!= this )
331 if( GetCancellableCount() < nPos
)
332 nPos
= GetCancellableCount();
336 //----------------------------------------------------------------
337 class SfxMedium_Impl
: public SvCompatWeakBase
340 ::ucbhelper::Content aContent
;
341 sal_Bool bUpdatePickList
: 1;
342 sal_Bool bIsTemp
: 1;
343 sal_Bool bForceSynchron
: 1;
344 sal_Bool bDontCreateCancellable
: 1;
345 sal_Bool bDownloadDone
: 1;
346 sal_Bool bDontCallDoneLinkOnSharingError
: 1;
347 sal_Bool bIsStorage
: 1;
348 sal_Bool bUseInteractionHandler
: 1;
349 sal_Bool bAllowDefaultIntHdl
: 1;
350 sal_Bool bIsCharsetInitialized
: 1;
351 sal_Bool bDisposeStorage
: 1;
352 sal_Bool bStorageBasedOnInStream
: 1;
353 sal_Bool m_bSalvageMode
: 1;
354 sal_Bool m_bVersionsAlreadyLoaded
: 1;
355 sal_Bool m_bLocked
: 1;
356 sal_Bool m_bGotDateTime
: 1;
358 uno::Reference
< embed::XStorage
> xStorage
;
360 SfxPoolCancelManager_ImplRef xCancelManager
;
361 SfxMedium
* pAntiImpl
;
365 const SfxFilter
* pOrigFilter
;
367 String aPreRedirectionURL
;
369 DateTime aExpireTime
;
370 SfxFrameWeak wLoadTargetFrame
;
371 SvKeyValueIteratorRef xAttributes
;
373 svtools::AsynchronLink aDoneLink
;
374 svtools::AsynchronLink aAvailableLink
;
376 uno::Sequence
< util::RevisionTag
> aVersions
;
378 ::utl::TempFile
* pTempFile
;
380 uno::Reference
< embed::XStorage
> m_xZipStorage
;
381 Reference
< XInputStream
> xInputStream
;
382 Reference
< XStream
> xStream
;
384 sal_uInt32 nLastStorageError
;
385 ::rtl::OUString aCharset
;
387 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
> xInteraction
;
389 sal_Bool m_bRemoveBackup
;
390 ::rtl::OUString m_aBackupURL
;
392 // the following member is changed and makes sence only during saving
393 // TODO/LATER: in future the signature state should be controlled by the medium not by the document
394 // in this case the member will hold this information
395 sal_uInt16 m_nSignatureState
;
397 util::DateTime m_aDateTime
;
399 uno::Reference
< logging::XSimpleLogRing
> m_xLogRing
;
401 SfxPoolCancelManager_Impl
* GetCancelManager();
403 SfxMedium_Impl( SfxMedium
* pAntiImplP
);
407 void SfxMedium::DataAvailable_Impl()
409 pImp
->aAvailableLink
.ClearPendingCall();
410 pImp
->aAvailableLink
.Call( NULL
);
413 void SfxMedium::Cancel_Impl()
415 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
418 SfxPoolCancelManager_Impl
* SfxMedium_Impl::GetCancelManager()
420 if( !xCancelManager
.Is() )
422 if( !bDontCreateCancellable
)
423 xCancelManager
= new SfxPoolCancelManager_Impl(
424 wLoadTargetFrame
? wLoadTargetFrame
->GetCancelManager() :
425 SFX_APP()->GetCancelManager(),
426 pAntiImpl
->GetURLObject().GetURLNoPass() );
428 xCancelManager
= new SfxPoolCancelManager_Impl(
429 0, pAntiImpl
->GetURLObject().GetURLNoPass() );
431 return xCancelManager
;
434 //------------------------------------------------------------------
435 SfxMedium_Impl::SfxMedium_Impl( SfxMedium
* pAntiImplP
)
436 : SvCompatWeakBase( pAntiImplP
),
437 bUpdatePickList(sal_True
),
438 bIsTemp( sal_False
),
439 bForceSynchron( sal_False
),
440 bDontCreateCancellable( sal_False
),
441 bDownloadDone( sal_True
),
442 bDontCallDoneLinkOnSharingError( sal_False
),
443 bIsStorage( sal_False
),
444 bUseInteractionHandler( sal_True
),
445 bAllowDefaultIntHdl( sal_False
),
446 bIsCharsetInitialized( sal_False
),
447 bStorageBasedOnInStream( sal_False
),
448 m_bSalvageMode( sal_False
),
449 m_bVersionsAlreadyLoaded( sal_False
),
450 m_bLocked( sal_False
),
451 m_bGotDateTime( sal_False
),
452 pAntiImpl( pAntiImplP
),
455 aExpireTime( Date() + 10, Time() ),
457 nLastStorageError( 0 ),
458 m_bRemoveBackup( sal_False
),
459 m_nSignatureState( SIGNATURESTATE_NOSIGNATURES
)
461 aDoneLink
.CreateMutex();
464 //------------------------------------------------------------------
465 SfxMedium_Impl::~SfxMedium_Impl()
468 aDoneLink
.ClearPendingCall();
469 aAvailableLink
.ClearPendingCall();
475 //================================================================
477 #define IMPL_CTOR(rootVal,URLVal) \
478 eError( SVSTREAM_OK ), \
480 bDirect( sal_False ), \
482 bSetFilter( sal_False ), \
483 bTriedStorage( sal_False ), \
485 nStorOpenMode( SFX_STREAM_READWRITE ), \
490 //------------------------------------------------------------------
491 void SfxMedium::ResetError()
493 eError
= SVSTREAM_OK
;
495 pInStream
->ResetError();
497 pOutStream
->ResetError();
500 //------------------------------------------------------------------
501 sal_uInt32
SfxMedium::GetLastStorageCreationState()
503 return pImp
->nLastStorageError
;
506 //------------------------------------------------------------------
507 void SfxMedium::AddLog( const ::rtl::OUString
& aMessage
)
509 if ( !pImp
->m_xLogRing
.is() )
513 ::comphelper::ComponentContext
aContext( ::comphelper::getProcessServiceFactory() );
515 pImp
->m_xLogRing
.set( aContext
.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), UNO_QUERY_THROW
);
517 catch( uno::Exception
& )
521 if ( pImp
->m_xLogRing
.is() )
522 pImp
->m_xLogRing
->logString( aMessage
);
525 //------------------------------------------------------------------
526 void SfxMedium::SetError( sal_uInt32 nError
, const ::rtl::OUString
& aLogMessage
)
529 if ( eError
!= ERRCODE_NONE
&& aLogMessage
.getLength() )
530 AddLog( aLogMessage
);
533 //------------------------------------------------------------------
534 sal_uInt32
SfxMedium::GetErrorCode() const
536 sal_uInt32 lError
=eError
;
537 if(!lError
&& pInStream
)
538 lError
=pInStream
->GetErrorCode();
539 if(!lError
&& pOutStream
)
540 lError
=pOutStream
->GetErrorCode();
544 //------------------------------------------------------------------
545 void SfxMedium::CheckFileDate( const util::DateTime
& aInitDate
)
547 GetInitFileDate( sal_True
);
548 if ( pImp
->m_aDateTime
.Seconds
!= aInitDate
.Seconds
549 || pImp
->m_aDateTime
.Minutes
!= aInitDate
.Minutes
550 || pImp
->m_aDateTime
.Hours
!= aInitDate
.Hours
551 || pImp
->m_aDateTime
.Day
!= aInitDate
.Day
552 || pImp
->m_aDateTime
.Month
!= aInitDate
.Month
553 || pImp
->m_aDateTime
.Year
!= aInitDate
.Year
)
555 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
561 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
562 document::ChangedByOthersRequest() ) );
563 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 3 );
564 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl
.get() );
565 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl
.get() );
566 xInteractionRequestImpl
->setContinuations( aContinuations
);
568 xHandler
->handle( xInteractionRequestImpl
.get() );
570 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xInteractionRequestImpl
->getSelection();
571 if ( uno::Reference
< task::XInteractionAbort
>( xSelected
.get(), uno::UNO_QUERY
).is() )
573 SetError( ERRCODE_ABORT
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
576 catch ( uno::Exception
& )
582 //------------------------------------------------------------------
583 sal_Bool
SfxMedium::DocNeedsFileDateCheck()
585 return ( !IsReadOnly() && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) );
588 //------------------------------------------------------------------
589 util::DateTime
SfxMedium::GetInitFileDate( sal_Bool bIgnoreOldValue
)
591 if ( ( bIgnoreOldValue
|| !pImp
->m_bGotDateTime
) && GetContent().is() )
595 pImp
->aContent
.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "DateModified" )) ) >>= pImp
->m_aDateTime
;
596 pImp
->m_bGotDateTime
= sal_True
;
598 catch ( ::com::sun::star::uno::Exception
& )
603 return pImp
->m_aDateTime
;
606 //------------------------------------------------------------------
607 Reference
< XContent
> SfxMedium::GetContent() const
609 if ( !pImp
->aContent
.get().is() )
611 Reference
< ::com::sun::star::ucb::XContent
> xContent
;
612 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
614 SFX_ITEMSET_ARG( pSet
, pItem
, SfxUnoAnyItem
, SID_CONTENT
, sal_False
);
616 pItem
->GetValue() >>= xContent
;
622 pImp
->aContent
= ::ucbhelper::Content( xContent
, xEnv
);
630 // TODO: DBG_ERROR("SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
633 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aURL
);
634 else if ( aLogicName
.Len() )
635 aURL
= GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
637 ::ucbhelper::Content::create( aURL
, xEnv
, pImp
->aContent
);
641 return pImp
->aContent
.get();
644 //------------------------------------------------------------------
645 ::rtl::OUString
SfxMedium::GetBaseURL( bool bForSaving
)
647 ::rtl::OUString aBaseURL
;
648 const SfxStringItem
* pBaseURLItem
= static_cast<const SfxStringItem
*>( GetItemSet()->GetItem(SID_DOC_BASEURL
) );
650 aBaseURL
= pBaseURLItem
->GetValue();
651 else if ( GetContent().is() )
655 Any aAny
= pImp
->aContent
.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI" )) );
658 catch ( ::com::sun::star::uno::Exception
& )
662 if ( !aBaseURL
.getLength() )
663 aBaseURL
= GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
669 sal_Bool bIsRemote
= IsRemote();
670 if( (bIsRemote
&& !aOpt
.IsSaveRelINet()) || (!bRemote
&& !aOpt
.IsSaveRelFSys()) )
671 return ::rtl::OUString();
677 //------------------------------------------------------------------
678 SvStream
* SfxMedium::GetInStream()
683 if ( pImp
->pTempFile
)
685 pInStream
= new SvFileStream( aName
, nStorOpenMode
);
687 eError
= pInStream
->GetError();
689 if( !eError
&& (nStorOpenMode
& STREAM_WRITE
)
690 && ! pInStream
->IsWritable() )
692 eError
= ERRCODE_IO_ACCESSDENIED
;
708 //------------------------------------------------------------------
709 void SfxMedium::CloseInStream()
711 CloseInStream_Impl();
714 void SfxMedium::CloseInStream_Impl()
716 // if there is a storage based on the InStream, we have to
717 // close the storage, too, because otherwise the storage
718 // would use an invalid ( deleted ) stream.
719 if ( pInStream
&& pImp
->xStorage
.is() )
721 if ( pImp
->bStorageBasedOnInStream
)
725 if ( pInStream
&& !GetContent().is() )
727 CreateTempFile( sal_True
);
731 DELETEZ( pInStream
);
733 pSet
->ClearItem( SID_INPUTSTREAM
);
735 CloseZipStorage_Impl();
736 pImp
->xInputStream
= uno::Reference
< io::XInputStream
>();
740 // output part of the stream is not used so the whole stream can be closed
741 // TODO/LATER: is it correct?
742 pImp
->xStream
= uno::Reference
< io::XStream
>();
744 pSet
->ClearItem( SID_STREAM
);
748 //------------------------------------------------------------------
749 SvStream
* SfxMedium::GetOutStream()
753 // Create a temp. file if there is none because we always
755 CreateTempFile( sal_False
);
757 if ( pImp
->pTempFile
)
759 pOutStream
= new SvFileStream( aName
, STREAM_STD_READWRITE
);
767 //------------------------------------------------------------------
768 sal_Bool
SfxMedium::CloseOutStream()
770 CloseOutStream_Impl();
774 sal_Bool
SfxMedium::CloseOutStream_Impl()
778 // if there is a storage based on the OutStream, we have to
779 // close the storage, too, because otherwise the storage
780 // would use an invalid ( deleted ) stream.
781 //TODO/MBA: how to deal with this?!
782 //maybe we need a new flag when the storage was created from the outstream
783 if ( pImp
->xStorage
.is() )
785 //const SvStream *pStorage = aStorage->GetSvStream();
786 //if ( pStorage == pOutStream )
796 // input part of the stream is not used so the whole stream can be closed
797 // TODO/LATER: is it correct?
798 pImp
->xStream
= uno::Reference
< io::XStream
>();
800 pSet
->ClearItem( SID_STREAM
);
806 //------------------------------------------------------------------
807 const String
& SfxMedium::GetPhysicalName() const
809 if ( !aName
.Len() && aLogicName
.Len() )
810 (( SfxMedium
*)this)->CreateFileStream();
812 // return the name then
816 //------------------------------------------------------------------
817 void SfxMedium::CreateFileStream()
819 ForceSynchronStream_Impl( TRUE
);
823 CreateTempFile( sal_False
);
824 pImp
->bIsTemp
= sal_True
;
825 CloseInStream_Impl();
829 //------------------------------------------------------------------
830 sal_Bool
SfxMedium::Commit()
832 if( pImp
->xStorage
.is() )
833 StorageCommit_Impl();
834 else if( pOutStream
)
839 if ( GetError() == SVSTREAM_OK
)
841 // does something only in case there is a temporary file ( means aName points to different location than aLogicName )
845 sal_Bool bResult
= ( GetError() == SVSTREAM_OK
);
847 if ( bResult
&& DocNeedsFileDateCheck() )
848 GetInitFileDate( sal_True
);
850 // remove truncation mode from the flags
851 nStorOpenMode
&= (~STREAM_TRUNC
);
855 //------------------------------------------------------------------
856 sal_Bool
SfxMedium::IsStorage()
858 if ( pImp
->xStorage
.is() )
862 return pImp
->bIsStorage
;
864 if ( pImp
->pTempFile
)
867 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aURL
) )
869 DBG_ERROR("Physical name not convertable!");
871 pImp
->bIsStorage
= SotStorage::IsStorageFile( aURL
) && !SotStorage::IsOLEStorage( aURL
);
872 if ( !pImp
->bIsStorage
)
873 bTriedStorage
= TRUE
;
875 else if ( GetInStream() )
877 pImp
->bIsStorage
= SotStorage::IsStorageFile( pInStream
) && !SotStorage::IsOLEStorage( pInStream
);
878 if ( !pInStream
->GetError() && !pImp
->bIsStorage
)
879 bTriedStorage
= TRUE
;
882 return pImp
->bIsStorage
;
885 //------------------------------------------------------------------
886 Link
SfxMedium::GetDataAvailableLink() const
888 return pImp
->aAvailableLink
.GetLink();
891 //------------------------------------------------------------------
892 Link
SfxMedium::GetDoneLink() const
894 return pImp
->aDoneLink
.GetLink();
897 //------------------------------------------------------------------
898 sal_Bool
SfxMedium::IsPreview_Impl()
900 sal_Bool bPreview
= sal_False
;
901 SFX_ITEMSET_ARG( GetItemSet(), pPreview
, SfxBoolItem
, SID_PREVIEW
, sal_False
);
903 bPreview
= pPreview
->GetValue();
906 SFX_ITEMSET_ARG( GetItemSet(), pFlags
, SfxStringItem
, SID_OPTIONS
, sal_False
);
909 String aFileFlags
= pFlags
->GetValue();
910 aFileFlags
.ToUpperAscii();
911 if ( STRING_NOTFOUND
!= aFileFlags
.Search( 'B' ) )
919 //------------------------------------------------------------------
920 void SfxMedium::StorageBackup_Impl()
922 ::ucbhelper::Content aOriginalContent
;
923 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
925 sal_Bool bBasedOnOriginalFile
= ( !pImp
->pTempFile
&& !( aLogicName
.Len() && pImp
->m_bSalvageMode
)
926 && GetURLObject().GetMainURL( INetURLObject::NO_DECODE
).getLength()
927 && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
928 && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) );
930 if ( bBasedOnOriginalFile
&& !pImp
->m_aBackupURL
.getLength()
931 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, aOriginalContent
) )
933 DoInternalBackup_Impl( aOriginalContent
);
934 if( !pImp
->m_aBackupURL
.getLength() )
935 SetError( ERRCODE_SFX_CANTCREATEBACKUP
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
939 //------------------------------------------------------------------
940 ::rtl::OUString
SfxMedium::GetBackup_Impl()
942 if ( !pImp
->m_aBackupURL
.getLength() )
943 StorageBackup_Impl();
945 return pImp
->m_aBackupURL
;
948 //------------------------------------------------------------------
949 uno::Reference
< embed::XStorage
> SfxMedium::GetOutputStorage()
952 return uno::Reference
< embed::XStorage
>();
954 // if the medium was constructed with a Storage: use this one, not a temp. storage
955 // if a temporary storage already exists: use it
956 if ( pImp
->xStorage
.is() && ( !aLogicName
.Len() || pImp
->pTempFile
) )
957 return pImp
->xStorage
;
959 // if necessary close stream that was used for reading
960 if ( pInStream
&& !pInStream
->IsWritable() )
963 DBG_ASSERT( !pOutStream
, "OutStream in a readonly Medium?!" );
965 // TODO/LATER: The current solution is to store the document temporary and then copy it to the target location;
966 // in future it should be stored directly and then copied to the temporary location, since in this case no
967 // file attributes have to be preserved and system copying mechanics could be used instead of streaming.
968 CreateTempFileNoCopy();
973 //------------------------------------------------------------------
974 void SfxMedium::SetPasswordToStorage_Impl()
976 // in case media-descriptor contains password it should be used on opening
977 if ( pImp
->xStorage
.is() && pSet
)
979 ::rtl::OUString aPasswd
;
980 if ( GetPasswd_Impl( pSet
, aPasswd
) )
984 ::comphelper::OStorageHelper::SetCommonStoragePassword( pImp
->xStorage
, aPasswd
);
986 catch( uno::Exception
& )
988 OSL_ENSURE( sal_False
, "It must be possible to set a common password for the storage" );
989 // TODO/LATER: set the error code in case of problem
990 // SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
996 //------------------------------------------------------------------
997 sal_Int8
SfxMedium::ShowLockedDocumentDialog( const uno::Sequence
< ::rtl::OUString
>& aData
, sal_Bool bIsLoading
, sal_Bool bOwnLock
)
999 sal_Int8 nResult
= LOCK_UI_NOLOCK
;
1001 // show the interaction regarding the document opening
1002 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
1004 if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler
.is() && ( bIsLoading
|| bOwnLock
) )
1006 ::rtl::OUString aDocumentURL
= GetURLObject().GetLastName();
1007 ::rtl::OUString aInfo
;
1008 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xInteractionRequestImpl
;
1012 if ( aData
.getLength() > LOCKFILE_EDITTIME_ID
)
1013 aInfo
= aData
[LOCKFILE_EDITTIME_ID
];
1015 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
1016 document::OwnLockOnDocumentRequest( ::rtl::OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
, !bIsLoading
) ) );
1020 if ( aData
.getLength() > LOCKFILE_EDITTIME_ID
)
1022 if ( aData
[LOCKFILE_OOOUSERNAME_ID
].getLength() )
1023 aInfo
= aData
[LOCKFILE_OOOUSERNAME_ID
];
1025 aInfo
= aData
[LOCKFILE_SYSUSERNAME_ID
];
1027 if ( aInfo
.getLength() && aData
[LOCKFILE_EDITTIME_ID
].getLength() )
1029 aInfo
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " ( " ) );
1030 aInfo
+= aData
[LOCKFILE_EDITTIME_ID
];
1031 aInfo
+= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " )" ) );
1037 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
1038 document::LockedDocumentRequest( ::rtl::OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
) ) );
1042 xInteractionRequestImpl
= new ::ucbhelper::InteractionRequest( uno::makeAny(
1043 document::LockedOnSavingRequest( ::rtl::OUString(), uno::Reference
< uno::XInterface
>(), aDocumentURL
, aInfo
) ) );
1048 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 3 );
1049 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl
.get() );
1050 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl
.get() );
1051 aContinuations
[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl
.get() );
1052 xInteractionRequestImpl
->setContinuations( aContinuations
);
1054 xHandler
->handle( xInteractionRequestImpl
.get() );
1056 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xInteractionRequestImpl
->getSelection();
1057 if ( uno::Reference
< task::XInteractionAbort
>( xSelected
.get(), uno::UNO_QUERY
).is() )
1059 SetError( ERRCODE_ABORT
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1061 else if ( uno::Reference
< task::XInteractionDisapprove
>( xSelected
.get(), uno::UNO_QUERY
).is() )
1063 // own lock on loading, user has selected to ignore the lock
1064 // own lock on saving, user has selected to ignore the lock
1065 // alien lock on loading, user has selected to edit a copy of document
1066 // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
1067 if ( bIsLoading
&& !bOwnLock
)
1069 // means that a copy of the document should be opened
1070 GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE
, sal_True
) );
1072 else if ( bOwnLock
)
1073 nResult
= LOCK_UI_SUCCEEDED
;
1075 else // if ( XSelected == aContinuations[1] )
1077 // own lock on loading, user has selected to open readonly
1078 // own lock on saving, user has selected to open readonly
1079 // alien lock on loading, user has selected to retry saving
1080 // TODO/LATER: alien lock on saving, user has selected to retry saving
1083 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
1085 nResult
= LOCK_UI_TRY
;
1092 // if no interaction handler is provided the default answer is open readonly
1093 // that usually happens in case the document is loaded per API
1094 // so the document must be opened readonly for backward compatibility
1095 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
1098 SetError( ERRCODE_IO_ACCESSDENIED
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1105 //------------------------------------------------------------------
1106 sal_Bool
SfxMedium::LockOrigFileOnDemand( sal_Bool bLoading
, sal_Bool bNoUI
)
1108 // returns true if the document can be opened for editing ( even if it should be a copy )
1109 // otherwise the document should be opened readonly
1110 // if user cancel the loading the ERROR_ABORT is set
1112 sal_Bool bResult
= pImp
->m_bLocked
;
1116 // no read-write access is necessary on loading if the document is explicitly opened as copy
1117 SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem
, SfxBoolItem
, SID_TEMPLATE
, sal_False
);
1118 bResult
= ( bLoading
&& pTemplateItem
&& pTemplateItem
->GetValue() );
1121 if ( !bResult
&& !IsReadOnly() )
1123 // check whether the file is readonly in fs
1124 // the check is only necessary if
1125 // do it only for loading, some contents still might have problems with this property, let them not affect the saving
1126 sal_Bool bContentReadonly
= sal_False
;
1127 if ( bLoading
&& ::utl::LocalFileHelper::IsLocalFile( aLogicName
) )
1129 // let the stream be opened to check the possibility to open it for editing
1133 // "IsReadOnly" property does not allow to detect whether the file is readonly always
1134 // so we try always to open the file for editing
1135 // the file is readonly only in case the read-write stream can not be opened
1136 SFX_ITEMSET_ARG( pSet
, pWriteStreamItem
, SfxUnoAnyItem
, SID_STREAM
, sal_False
);
1137 if ( bLoading
&& !pWriteStreamItem
)
1141 // MediaDescriptor does this check also, the duplication should be avoided in future
1142 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1143 ::ucbhelper::Content
aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
);
1144 aContent
.getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) ) >>= bContentReadonly
;
1146 catch( uno::Exception
)
1150 // do further checks only if the file not readonly in fs
1151 if ( !bContentReadonly
)
1153 // the special file locking should be used only for file URLs
1154 if ( ::utl::LocalFileHelper::IsLocalFile( aLogicName
) )
1157 // in case of storing the document should request the output before locking
1160 // let the stream be opened to check the system file locking
1164 sal_Int8 bUIStatus
= LOCK_UI_NOLOCK
;
1166 // check whether system file locking has been used, the default value is false
1167 sal_Bool bUseSystemLock
= IsSystemFileLockingUsed();
1169 // TODO/LATER: This implementation does not allow to detect the system lock on saving here, actually this is no big problem
1170 // if system lock is used the writeable stream should be available
1171 sal_Bool bHandleSysLocked
= ( bLoading
&& bUseSystemLock
&& !pImp
->xStream
.is() && !pOutStream
);
1177 ::svt::DocumentLockFile
aLockFile( aLogicName
);
1178 if ( !bHandleSysLocked
)
1182 bResult
= aLockFile
.CreateOwnLockFile();
1184 catch ( ucb::InteractiveIOException
& e
)
1186 // exception means that the lock file can not be successfuly accessed
1187 // in this case it should be ignored if system file locking is anyway active
1188 if ( bUseSystemLock
|| !IsOOoLockFileUsed() )
1191 // take the ownership over the lock file
1192 aLockFile
.OverwriteOwnLockFile();
1194 else if ( e
.Code
== IOErrorCode_INVALID_PARAMETER
)
1196 // system file locking is not active, ask user whether he wants to open the document without any locking
1197 uno::Reference
< task::XInteractionHandler
> xHandler
= GetInteractionHandler();
1199 if ( xHandler
.is() )
1201 ::rtl::Reference
< ::ucbhelper::InteractionRequest
> xIgnoreRequestImpl
1202 = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
1204 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( 2 );
1205 aContinuations
[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl
.get() );
1206 aContinuations
[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl
.get() );
1207 xIgnoreRequestImpl
->setContinuations( aContinuations
);
1209 xHandler
->handle( xIgnoreRequestImpl
.get() );
1211 ::rtl::Reference
< ::ucbhelper::InteractionContinuation
> xSelected
= xIgnoreRequestImpl
->getSelection();
1212 bResult
= ( uno::Reference
< task::XInteractionApprove
>( xSelected
.get(), uno::UNO_QUERY
).is() );
1216 catch ( uno::Exception
& )
1218 // exception means that the lock file can not be successfuly accessed
1219 // in this case it should be ignored if system file locking is anyway active
1220 if ( bUseSystemLock
|| !IsOOoLockFileUsed() )
1223 // take the ownership over the lock file
1224 aLockFile
.OverwriteOwnLockFile();
1228 // in case OOo locking is turned off the lock file is still written if possible
1229 // but it is ignored while deciding whether the document should be opened for editing or not
1230 if ( !bResult
&& !IsOOoLockFileUsed() )
1233 // take the ownership over the lock file
1234 aLockFile
.OverwriteOwnLockFile();
1241 uno::Sequence
< ::rtl::OUString
> aData
;
1244 // impossibility to get data is no real problem
1245 aData
= aLockFile
.GetLockData();
1247 catch( uno::Exception
) {}
1249 sal_Bool bOwnLock
= sal_False
;
1251 if ( !bHandleSysLocked
)
1253 uno::Sequence
< ::rtl::OUString
> aOwnData
= aLockFile
.GenerateOwnEntry();
1254 bOwnLock
= ( aData
.getLength() > LOCKFILE_USERURL_ID
1255 && aOwnData
.getLength() > LOCKFILE_USERURL_ID
1256 && aOwnData
[LOCKFILE_SYSUSERNAME_ID
].equals( aData
[LOCKFILE_SYSUSERNAME_ID
] ) );
1259 && aOwnData
[LOCKFILE_LOCALHOST_ID
].equals( aData
[LOCKFILE_LOCALHOST_ID
] )
1260 && aOwnData
[LOCKFILE_USERURL_ID
].equals( aData
[LOCKFILE_USERURL_ID
] ) )
1262 // this is own lock from the same installation, it could remain because of crash
1267 if ( !bResult
&& !bNoUI
)
1269 bUIStatus
= ShowLockedDocumentDialog( aData
, bLoading
, bOwnLock
);
1270 if ( bUIStatus
== LOCK_UI_SUCCEEDED
)
1272 // take the ownership over the lock file
1273 bResult
= aLockFile
.OverwriteOwnLockFile();
1277 bHandleSysLocked
= sal_False
;
1280 catch( uno::Exception
& )
1283 } while( !bResult
&& bUIStatus
== LOCK_UI_TRY
);
1285 pImp
->m_bLocked
= bResult
;
1289 // this is no file URL, check whether the file is readonly
1290 bResult
= !bContentReadonly
;
1295 if ( !bResult
&& GetError() == ERRCODE_NONE
)
1297 // the error should be set in case it is storing process
1298 // or the document has been opened for editing explicitly
1300 SFX_ITEMSET_ARG( pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, FALSE
);
1301 if ( !bLoading
|| (pReadOnlyItem
&& !pReadOnlyItem
->GetValue()) )
1302 SetError( ERRCODE_IO_ACCESSDENIED
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1304 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
1307 // when the file is locked, get the current file date
1308 if ( bResult
&& DocNeedsFileDateCheck() )
1309 GetInitFileDate( sal_True
);
1314 //------------------------------------------------------------------
1315 uno::Reference
< embed::XStorage
> SfxMedium::GetStorage( sal_Bool bCreateTempIfNo
)
1317 if ( pImp
->xStorage
.is() || bTriedStorage
)
1318 return pImp
->xStorage
;
1320 uno::Sequence
< uno::Any
> aArgs( 2 );
1322 // the medium should be retrieved before temporary file creation
1323 // to let the MediaDescriptor be filled with the streams
1326 if ( bCreateTempIfNo
)
1327 CreateTempFile( sal_False
);
1332 return pImp
->xStorage
;
1334 SFX_ITEMSET_ARG( GetItemSet(), pRepairItem
, SfxBoolItem
, SID_REPAIRPACKAGE
, sal_False
);
1335 if ( pRepairItem
&& pRepairItem
->GetValue() )
1337 // the storage should be created for repairing mode
1338 CreateTempFile( sal_False
);
1341 Reference
< ::com::sun::star::ucb::XProgressHandler
> xProgressHandler
;
1342 Reference
< ::com::sun::star::task::XStatusIndicator
> xStatusIndicator
;
1344 SFX_ITEMSET_ARG( GetItemSet(), pxProgressItem
, SfxUnoAnyItem
, SID_PROGRESS_STATUSBAR_CONTROL
, sal_False
);
1345 if( pxProgressItem
&& ( pxProgressItem
->GetValue() >>= xStatusIndicator
) )
1346 xProgressHandler
= Reference
< ::com::sun::star::ucb::XProgressHandler
>(
1347 new utl::ProgressHandlerWrap( xStatusIndicator
) );
1349 uno::Sequence
< beans::PropertyValue
> aAddProps( 2 );
1350 aAddProps
[0].Name
= ::rtl::OUString::createFromAscii( "RepairPackage" );
1351 aAddProps
[0].Value
<<= (sal_Bool
)sal_True
;
1352 aAddProps
[1].Name
= ::rtl::OUString::createFromAscii( "StatusIndicator" );
1353 aAddProps
[1].Value
<<= xProgressHandler
;
1355 // the first arguments will be filled later
1357 aArgs
[2] <<= aAddProps
;
1360 if ( pImp
->xStream
.is() )
1362 // since the storage is based on temporary stream we open it always read-write
1363 aArgs
[0] <<= pImp
->xStream
;
1364 aArgs
[1] <<= embed::ElementModes::READWRITE
;
1365 pImp
->bStorageBasedOnInStream
= sal_True
;
1367 else if ( pImp
->xInputStream
.is() )
1369 // since the storage is based on temporary stream we open it always read-write
1370 aArgs
[0] <<= pImp
->xInputStream
;
1371 aArgs
[1] <<= embed::ElementModes::READ
;
1372 pImp
->bStorageBasedOnInStream
= sal_True
;
1376 CloseStreams_Impl();
1377 aArgs
[0] <<= ::rtl::OUString( aName
);
1378 aArgs
[1] <<= embed::ElementModes::READ
;
1379 pImp
->bStorageBasedOnInStream
= sal_False
;
1384 pImp
->xStorage
= uno::Reference
< embed::XStorage
>(
1385 ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs
),
1388 catch( uno::Exception
& )
1390 // impossibility to create the storage is no error
1393 if( ( pImp
->nLastStorageError
= GetError() ) != SVSTREAM_OK
)
1398 return uno::Reference
< embed::XStorage
>();
1401 bTriedStorage
= sal_True
;
1403 // TODO/LATER: Get versionlist on demand
1404 if ( pImp
->xStorage
.is() )
1406 SetPasswordToStorage_Impl();
1410 SFX_ITEMSET_ARG( pSet
, pVersion
, SfxInt16Item
, SID_VERSION
, sal_False
);
1412 BOOL bResetStorage
= FALSE
;
1413 if ( pVersion
&& pVersion
->GetValue() )
1415 // Alle verf"ugbaren Versionen einlesen
1416 if ( pImp
->aVersions
.getLength() )
1418 // Die zum Kommentar passende Version suchen
1419 // Die Versionen sind von 1 an durchnumeriert, mit negativen
1420 // Versionsnummern werden die Versionen von der aktuellen aus
1421 // r"uckw"arts gez"ahlt
1422 short nVersion
= pVersion
? pVersion
->GetValue() : 0;
1424 nVersion
= ( (short) pImp
->aVersions
.getLength() ) + nVersion
;
1425 else if ( nVersion
)
1428 util::RevisionTag
& rTag
= pImp
->aVersions
[nVersion
];
1430 // SubStorage f"ur alle Versionen "offnen
1431 uno::Reference
< embed::XStorage
> xSub
= pImp
->xStorage
->openStorageElement( DEFINE_CONST_UNICODE( "Versions" ),
1432 embed::ElementModes::READ
);
1434 DBG_ASSERT( xSub
.is(), "Versionsliste, aber keine Versionen!" );
1436 // Dort ist die Version als gepackter Stream gespeichert
1437 uno::Reference
< io::XStream
> xStr
= xSub
->openStreamElement( rTag
.Identifier
, embed::ElementModes::READ
);
1438 SvStream
* pStream
= utl::UcbStreamHelper::CreateStream( xStr
);
1439 if ( pStream
&& pStream
->GetError() == SVSTREAM_OK
)
1441 // Stream ins TempDir auspacken
1442 ::utl::TempFile aTempFile
;
1443 String aTmpName
= aTempFile
.GetURL();
1444 SvFileStream
aTmpStream( aTmpName
, SFX_STREAM_READWRITE
);
1446 *pStream
>> aTmpStream
;
1449 // Datei als Storage "offnen
1450 nStorOpenMode
= SFX_STREAM_READONLY
;
1451 pImp
->xStorage
= comphelper::OStorageHelper::GetStorageFromURL( aTmpName
, embed::ElementModes::READ
);
1452 pImp
->bStorageBasedOnInStream
= sal_False
;
1454 ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName
, aTemp
);
1455 SetPhysicalName_Impl( aTemp
);
1457 pImp
->bIsTemp
= sal_True
;
1458 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
1460 pImp
->aVersions
.realloc(0);
1463 bResetStorage
= TRUE
;
1467 bResetStorage
= TRUE
;
1470 if ( bResetStorage
)
1474 pInStream
->Seek( 0L );
1477 pImp
->bIsStorage
= pImp
->xStorage
.is();
1478 return pImp
->xStorage
;
1481 //------------------------------------------------------------------
1482 uno::Reference
< embed::XStorage
> SfxMedium::GetZipStorageToSign_Impl( sal_Bool bReadOnly
)
1484 if ( !GetError() && !pImp
->m_xZipStorage
.is() )
1487 // if bReadOnly == sal_False and there is no temporary file the original file might be used
1492 // we can not sign document if there is no stream
1493 // should it be possible at all?
1494 if ( !bReadOnly
&& pImp
->xStream
.is() )
1496 pImp
->m_xZipStorage
= ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xStream
, embed::ElementModes::READWRITE
);
1498 else if ( pImp
->xInputStream
.is() )
1500 pImp
->m_xZipStorage
= ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xInputStream
);
1503 catch( uno::Exception
& )
1505 OSL_ENSURE( sal_False
, "No possibility to get readonly version of storage from medium!\n" );
1508 if ( GetError() ) // do not remove warnings
1512 return pImp
->m_xZipStorage
;
1515 //------------------------------------------------------------------
1516 void SfxMedium::CloseZipStorage_Impl()
1518 if ( pImp
->m_xZipStorage
.is() )
1521 pImp
->m_xZipStorage
->dispose();
1522 } catch( uno::Exception
& )
1525 pImp
->m_xZipStorage
= uno::Reference
< embed::XStorage
>();
1529 //------------------------------------------------------------------
1530 void SfxMedium::CloseStorage()
1532 if ( pImp
->xStorage
.is() )
1534 uno::Reference
< lang::XComponent
> xComp( pImp
->xStorage
, uno::UNO_QUERY
);
1535 // in the salvage mode the medium does not own the storage
1536 if ( pImp
->bDisposeStorage
&& !pImp
->m_bSalvageMode
)
1540 } catch( uno::Exception
& )
1542 OSL_ENSURE( sal_False
, "Medium's storage is already disposed!\n" );
1547 pImp
->bStorageBasedOnInStream
= sal_False
;
1550 bTriedStorage
= sal_False
;
1551 pImp
->bIsStorage
= sal_False
;
1554 void SfxMedium::CanDisposeStorage_Impl( sal_Bool bDisposeStorage
)
1556 pImp
->bDisposeStorage
= bDisposeStorage
;
1559 sal_Bool
SfxMedium::WillDisposeStorageOnClose_Impl()
1561 return pImp
->bDisposeStorage
;
1564 //------------------------------------------------------------------
1565 void SfxMedium::SetOpenMode( StreamMode nStorOpen
,
1567 sal_Bool bDontClose
)
1569 if ( nStorOpenMode
!= nStorOpen
)
1571 nStorOpenMode
= nStorOpen
;
1575 if ( pImp
->xStorage
.is() )
1578 CloseStreams_Impl();
1583 bSetFilter
= sal_False
;
1586 //------------------------------------------------------------------
1587 sal_Bool
SfxMedium::UseBackupToRestore_Impl( ::ucbhelper::Content
& aOriginalContent
,
1588 const Reference
< ::com::sun::star::ucb::XCommandEnvironment
>& xComEnv
)
1592 ::ucbhelper::Content
aTransactCont( pImp
->m_aBackupURL
, xComEnv
);
1594 Reference
< XInputStream
> aOrigInput
= aTransactCont
.openStream();
1595 aOriginalContent
.writeStream( aOrigInput
, sal_True
);
1600 // in case of failure here the backup file should not be removed
1601 // TODO/LATER: a message should be used to let user know about the backup
1602 pImp
->m_bRemoveBackup
= sal_False
;
1603 // TODO/LATER: needs a specific error code
1604 eError
= ERRCODE_IO_GENERAL
;
1610 //------------------------------------------------------------------
1611 sal_Bool
SfxMedium::StorageCommit_Impl()
1613 sal_Bool bResult
= sal_False
;
1614 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1615 ::ucbhelper::Content aOriginalContent
;
1617 if ( pImp
->xStorage
.is() )
1621 uno::Reference
< embed::XTransactedObject
> xTrans( pImp
->xStorage
, uno::UNO_QUERY
);
1627 CloseZipStorage_Impl();
1630 catch ( embed::UseBackupException
& aBackupExc
)
1632 // since the temporary file is created always now, the scenario is close to be impossible
1633 if ( !pImp
->pTempFile
)
1635 OSL_ENSURE( pImp
->m_aBackupURL
.getLength(), "No backup on storage commit!\n" );
1636 if ( pImp
->m_aBackupURL
.getLength()
1637 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
),
1639 aOriginalContent
) )
1641 // use backup to restore the file
1642 // the storage has already disconnected from original location
1643 CloseAndReleaseStreams_Impl();
1644 if ( !UseBackupToRestore_Impl( aOriginalContent
, xDummyEnv
) )
1646 // connect the medium to the temporary file of the storage
1647 pImp
->aContent
= ::ucbhelper::Content();
1648 aName
= aBackupExc
.TemporaryFileURL
;
1649 OSL_ENSURE( aName
.Len(), "The exception _must_ contain the temporary URL!\n" );
1654 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1657 catch ( uno::Exception
& )
1659 //TODO/LATER: improve error handling
1660 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1669 //------------------------------------------------------------------
1670 sal_Bool
SfxMedium::TransactedTransferForFS_Impl( const INetURLObject
& aSource
,
1671 const INetURLObject
& aDest
,
1672 const Reference
< ::com::sun::star::ucb::XCommandEnvironment
>& xComEnv
)
1674 sal_Bool bResult
= sal_False
;
1675 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
1676 Reference
< XOutputStream
> aDestStream
;
1677 ::ucbhelper::Content aOriginalContent
;
1681 aOriginalContent
= ::ucbhelper::Content( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
1683 catch ( ::com::sun::star::ucb::CommandAbortedException
& )
1685 eError
= ERRCODE_ABORT
;
1687 catch ( ::com::sun::star::ucb::CommandFailedException
& )
1689 eError
= ERRCODE_ABORT
;
1691 catch (const ::com::sun::star::ucb::ContentCreationException
& ex
)
1693 eError
= ERRCODE_IO_GENERAL
;
1695 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER
) ||
1696 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED
)
1699 eError
= ERRCODE_IO_NOTEXISTSPATH
;
1702 catch (const ::com::sun::star::uno::Exception
&)
1704 eError
= ERRCODE_IO_GENERAL
;
1707 if( !eError
|| (eError
& ERRCODE_WARNING_MASK
) )
1709 if ( pImp
->xStorage
.is() )
1712 CloseStreams_Impl();
1714 ::ucbhelper::Content aTempCont
;
1715 if( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xDummyEnv
, aTempCont
) )
1717 sal_Bool bTransactStarted
= sal_False
;
1718 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, sal_False
);
1719 SFX_ITEMSET_ARG( GetItemSet(), pRename
, SfxBoolItem
, SID_RENAME
, sal_False
);
1720 sal_Bool bRename
= pRename
? pRename
->GetValue() : FALSE
;
1721 sal_Bool bOverWrite
= pOverWrite
? pOverWrite
->GetValue() : !bRename
;
1725 if( bOverWrite
&& ::utl::UCBContentHelper::IsDocument( aDest
.GetMainURL( INetURLObject::NO_DECODE
) ) )
1727 if( ! pImp
->m_aBackupURL
.getLength() )
1728 DoInternalBackup_Impl( aOriginalContent
);
1730 if( pImp
->m_aBackupURL
.getLength() )
1732 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1733 bTransactStarted
= sal_True
;
1734 aOriginalContent
.setPropertyValue( ::rtl::OUString::createFromAscii( "Size" ),
1735 uno::makeAny( (sal_Int64
)0 ) );
1736 aOriginalContent
.writeStream( aTempInput
, bOverWrite
);
1741 eError
= ERRCODE_SFX_CANTCREATEBACKUP
;
1746 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1747 aOriginalContent
.writeStream( aTempInput
, bOverWrite
);
1751 catch ( ::com::sun::star::ucb::CommandAbortedException
& )
1753 eError
= ERRCODE_ABORT
;
1755 catch ( ::com::sun::star::ucb::CommandFailedException
& )
1757 eError
= ERRCODE_ABORT
;
1759 catch ( ::com::sun::star::ucb::InteractiveIOException
& r
)
1761 if ( r
.Code
== IOErrorCode_ACCESS_DENIED
)
1762 eError
= ERRCODE_IO_ACCESSDENIED
;
1763 else if ( r
.Code
== IOErrorCode_NOT_EXISTING
)
1764 eError
= ERRCODE_IO_NOTEXISTS
;
1765 else if ( r
.Code
== IOErrorCode_CANT_READ
)
1766 eError
= ERRCODE_IO_CANTREAD
;
1768 eError
= ERRCODE_IO_GENERAL
;
1770 catch ( ::com::sun::star::uno::Exception
& )
1772 eError
= ERRCODE_IO_GENERAL
;
1777 if ( pImp
->pTempFile
)
1779 pImp
->pTempFile
->EnableKillingFile( sal_True
);
1780 delete pImp
->pTempFile
;
1781 pImp
->pTempFile
= NULL
;
1784 else if ( bTransactStarted
)
1786 UseBackupToRestore_Impl( aOriginalContent
, xDummyEnv
);
1790 eError
= ERRCODE_IO_CANTREAD
;
1796 //------------------------------------------------------------------
1797 sal_Bool
SfxMedium::TryDirectTransfer( const ::rtl::OUString
& aURL
, SfxItemSet
& aTargetSet
)
1802 // if the document had no password it should be stored without password
1803 // if the document had password it should be stored with the same password
1804 // otherwise the stream copying can not be done
1805 SFX_ITEMSET_ARG( &aTargetSet
, pNewPassItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
1806 SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
1807 if ( ( !pNewPassItem
&& !pOldPassItem
)
1808 || ( pNewPassItem
&& pOldPassItem
&& pNewPassItem
->GetValue().Equals( pOldPassItem
->GetValue() ) ) )
1810 // the filter must be the same
1811 SFX_ITEMSET_ARG( &aTargetSet
, pNewFilterItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
1812 SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
1813 if ( pNewFilterItem
&& pOldFilterItem
&& pNewFilterItem
->GetValue().Equals( pOldFilterItem
->GetValue() ) )
1815 // get the input stream and copy it
1816 // in case of success return true
1817 uno::Reference
< io::XInputStream
> xInStream
= GetInputStream();
1820 if ( xInStream
.is() )
1824 uno::Reference
< io::XSeekable
> xSeek( xInStream
, uno::UNO_QUERY
);
1828 nPos
= xSeek
->getPosition();
1832 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
1833 ::ucbhelper::Content
aTargetContent( aURL
, xEnv
);
1835 InsertCommandArgument aInsertArg
;
1836 aInsertArg
.Data
= xInStream
;
1837 SFX_ITEMSET_ARG( &aTargetSet
, pRename
, SfxBoolItem
, SID_RENAME
, sal_False
);
1838 SFX_ITEMSET_ARG( &aTargetSet
, pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, sal_False
);
1839 if ( (pOverWrite
&& !pOverWrite
->GetValue()) // argument says: never overwrite
1840 || (pRename
&& pRename
->GetValue()) ) // argument says: rename file
1841 aInsertArg
.ReplaceExisting
= sal_False
;
1843 aInsertArg
.ReplaceExisting
= sal_True
; // default is overwrite existing files
1846 aCmdArg
<<= aInsertArg
;
1847 aTargetContent
.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
1851 xSeek
->seek( nPos
);
1855 catch( uno::Exception
& )
1864 //------------------------------------------------------------------
1865 void SfxMedium::Transfer_Impl()
1867 // The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
1869 if ( pImp
->pTempFile
)
1870 aNameURL
= pImp
->pTempFile
->GetURL();
1871 else if ( aLogicName
.Len() && pImp
->m_bSalvageMode
)
1873 // makes sence only in case logic name is set
1874 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aNameURL
) )
1875 OSL_ENSURE( sal_False
, "The medium name is not convertable!\n" );
1878 if ( aNameURL
.Len() && ( !eError
|| (eError
& ERRCODE_WARNING_MASK
) ) )
1880 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::Transfer_Impl, copying to target" );
1882 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
1883 Reference
< XOutputStream
> rOutStream
;
1885 // in case an output stream is provided from outside and the URL is correct
1886 // commit to the stream
1887 if( aLogicName
.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL
)
1889 // TODO/LATER: support storing to SID_STREAM
1890 SFX_ITEMSET_ARG( pSet
, pOutStreamItem
, SfxUnoAnyItem
, SID_OUTPUTSTREAM
, sal_False
);
1891 if( pOutStreamItem
&& ( pOutStreamItem
->GetValue() >>= rOutStream
) )
1893 if ( pImp
->xStorage
.is() )
1896 CloseStreams_Impl();
1898 INetURLObject
aSource( aNameURL
);
1899 ::ucbhelper::Content aTempCont
;
1900 if( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, aTempCont
) )
1905 sal_Int32 nBufferSize
= 32767;
1906 Sequence
< sal_Int8
> aSequence ( nBufferSize
);
1907 Reference
< XInputStream
> aTempInput
= aTempCont
.openStream();
1911 nRead
= aTempInput
->readBytes ( aSequence
, nBufferSize
);
1912 if ( nRead
< nBufferSize
)
1914 Sequence
< sal_Int8
> aTempBuf ( aSequence
.getConstArray(), nRead
);
1915 rOutStream
->writeBytes ( aTempBuf
);
1918 rOutStream
->writeBytes ( aSequence
);
1920 while ( nRead
== nBufferSize
);
1922 // remove temporary file
1923 if ( pImp
->pTempFile
)
1925 pImp
->pTempFile
->EnableKillingFile( sal_True
);
1926 delete pImp
->pTempFile
;
1927 pImp
->pTempFile
= NULL
;
1936 DBG_ERROR( "Illegal Output stream parameter!\n" );
1937 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1940 // free the reference
1942 pSet
->ClearItem( SID_OUTPUTSTREAM
);
1948 if ( !pImp
->aContent
.get().is() )
1950 eError
= ERRCODE_IO_NOTEXISTS
;
1954 SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize
, SfxInt32Item
, SID_SEGMENTSIZE
, sal_False
);
1957 // this file must be stored into a disk spanned package
1960 uno::Reference
< embed::XStorage
> xStor
= comphelper::OStorageHelper::GetStorageFromURL( GetName(),
1961 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
1963 // set segment size property; package will automatically be divided in pieces fitting
1965 ::com::sun::star::uno::Any aAny
;
1966 aAny
<<= pSegmentSize
->GetValue();
1968 uno::Reference
< beans::XPropertySet
> xSet( pImp
->xStorage
, uno::UNO_QUERY
);
1969 xSet
->setPropertyValue( String::CreateFromAscii("SegmentSize"), aAny
);
1971 // copy the temporary storage into the disk spanned package
1972 GetStorage()->copyToStorage( xStor
);
1973 uno::Reference
< embed::XTransactedObject
> xTrans( pImp
->xStorage
, uno::UNO_QUERY
);
1978 catch ( uno::Exception
& )
1980 //TODO/MBA: error handling
1985 INetURLObject
aDest( GetURLObject() );
1987 // source is the temp file written so far
1988 INetURLObject
aSource( aNameURL
);
1990 // a special case, an interaction handler should be used for
1991 // authentication in case it is available
1992 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
1993 Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler
= GetInteractionHandler();
1994 if (xInteractionHandler
.is())
1995 xComEnv
= new ::ucbhelper::CommandEnvironment( xInteractionHandler
,
1996 Reference
< ::com::sun::star::ucb::XProgressHandler
>() );
1998 if ( ::utl::LocalFileHelper::IsLocalFile( aDest
.GetMainURL( INetURLObject::NO_DECODE
) ) || !aDest
.removeSegment() )
2000 TransactedTransferForFS_Impl( aSource
, aDest
, xComEnv
);
2004 // create content for the parent folder and call transfer on that content with the source content
2005 // and the destination file name as parameters
2006 ::ucbhelper::Content aSourceContent
;
2007 ::ucbhelper::Content aTransferContent
;
2009 String aFileName
= GetLongName();
2010 if ( !aFileName
.Len() )
2011 aFileName
= GetURLObject().getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2015 aTransferContent
= ::ucbhelper::Content( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
2017 catch (const ::com::sun::star::ucb::ContentCreationException
& ex
)
2019 eError
= ERRCODE_IO_GENERAL
;
2021 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER
) ||
2022 (ex
.eError
== ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED
)
2025 eError
= ERRCODE_IO_NOTEXISTSPATH
;
2028 catch (const ::com::sun::star::uno::Exception
&)
2030 eError
= ERRCODE_IO_GENERAL
;
2033 if ( !eError
|| (eError
& ERRCODE_WARNING_MASK
) )
2035 // free resources, otherwise the transfer may fail
2036 if ( pImp
->xStorage
.is() )
2039 CloseStreams_Impl();
2041 ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, aSourceContent
);
2043 // check for external parameters that may customize the handling of NameClash situations
2044 SFX_ITEMSET_ARG( GetItemSet(), pRename
, SfxBoolItem
, SID_RENAME
, sal_False
);
2045 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite
, SfxBoolItem
, SID_OVERWRITE
, sal_False
);
2046 sal_Int32 nNameClash
;
2047 if ( pOverWrite
&& !pOverWrite
->GetValue() )
2048 // argument says: never overwrite
2049 nNameClash
= NameClash::ERROR
;
2050 else if ( pRename
&& pRename
->GetValue() )
2051 // argument says: rename file
2052 nNameClash
= NameClash::RENAME
;
2054 // default is overwrite existing files
2055 nNameClash
= NameClash::OVERWRITE
;
2059 if (!aTransferContent
.transferContent( aSourceContent
, ::ucbhelper::InsertOperation_COPY
, aFileName
, nNameClash
))
2060 eError
= ERRCODE_IO_GENERAL
;
2062 catch ( ::com::sun::star::ucb::CommandAbortedException
& )
2064 eError
= ERRCODE_ABORT
;
2066 catch ( ::com::sun::star::ucb::CommandFailedException
& )
2068 eError
= ERRCODE_ABORT
;
2070 catch ( ::com::sun::star::ucb::InteractiveIOException
& r
)
2072 if ( r
.Code
== IOErrorCode_ACCESS_DENIED
)
2073 eError
= ERRCODE_IO_ACCESSDENIED
;
2074 else if ( r
.Code
== IOErrorCode_NOT_EXISTING
)
2075 eError
= ERRCODE_IO_NOTEXISTS
;
2076 else if ( r
.Code
== IOErrorCode_CANT_READ
)
2077 eError
= ERRCODE_IO_CANTREAD
;
2079 eError
= ERRCODE_IO_GENERAL
;
2081 catch ( ::com::sun::star::uno::Exception
& )
2083 eError
= ERRCODE_IO_GENERAL
;
2086 // do not switch from temporary file in case of nonfile protocol
2090 if ( ( !eError
|| (eError
& ERRCODE_WARNING_MASK
) ) && !pImp
->pTempFile
)
2092 // without a TempFile the physical and logical name should be the same after successful transfer
2093 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
),
2095 pImp
->m_bSalvageMode
= sal_False
;
2100 //------------------------------------------------------------------
2101 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content
& aOriginalContent
,
2102 const String
& aPrefix
,
2103 const String
& aExtension
,
2104 const String
& aDestDir
)
2106 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::DoInternalBackup_Impl( with destdir )" );
2108 if ( pImp
->m_aBackupURL
.getLength() )
2109 return; // the backup was done already
2111 ::rtl::OUString aBackupName
;
2112 ::rtl::OUString aBackupURL
;
2114 // a living aTransactTemp kills WebDAV with SAL_ENABLE_FILE_LOCKING=1,
2115 // because then it attempts to have 2 file handles pointing to the same
2117 ::utl::TempFile
aTransactTemp( aPrefix
, &aExtension
, &aDestDir
);
2118 aTransactTemp
.EnableKillingFile( sal_True
);
2120 INetURLObject
aBackObj( aTransactTemp
.GetURL() );
2122 aBackupName
= aBackObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2123 aBackupURL
= aBackObj
.GetMainURL( INetURLObject::NO_DECODE
);
2126 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xDummyEnv
;
2127 ::ucbhelper::Content aBackupCont
;
2128 if( ::ucbhelper::Content::create( aDestDir
, xDummyEnv
, aBackupCont
) )
2132 if( aBackupCont
.transferContent( aOriginalContent
,
2133 ::ucbhelper::InsertOperation_COPY
,
2135 NameClash::OVERWRITE
) )
2137 pImp
->m_aBackupURL
= aBackupURL
;
2138 pImp
->m_bRemoveBackup
= sal_True
;
2146 //------------------------------------------------------------------
2147 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content
& aOriginalContent
)
2149 if ( pImp
->m_aBackupURL
.getLength() )
2150 return; // the backup was done already
2152 ::rtl::OUString aFileName
= GetURLObject().getName( INetURLObject::LAST_SEGMENT
,
2154 INetURLObject::NO_DECODE
);
2156 sal_Int32 nPrefixLen
= aFileName
.lastIndexOf( '.' );
2157 String aPrefix
= ( nPrefixLen
== -1 ) ? aFileName
: aFileName
.copy( 0, nPrefixLen
);
2158 String aExtension
= ( nPrefixLen
== -1 ) ? String() : String(aFileName
.copy( nPrefixLen
));
2159 String aBakDir
= SvtPathOptions().GetBackupPath();
2161 DoInternalBackup_Impl( aOriginalContent
, aPrefix
, aExtension
, aBakDir
);
2163 if ( !pImp
->m_aBackupURL
.getLength() )
2165 // the copiing to the backup catalog failed ( for example because
2166 // of using an encrypted partition as target catalog )
2167 // since the user did not specify to make backup explicitly
2168 // office should try to make backup in another place,
2169 // target catalog does not look bad for this case ( and looks
2170 // to be the only way for encrypted partitions )
2172 INetURLObject aDest
= GetURLObject();
2173 if ( aDest
.removeSegment() )
2174 DoInternalBackup_Impl( aOriginalContent
, aPrefix
, aExtension
, aDest
.GetMainURL( INetURLObject::NO_DECODE
) );
2179 //------------------------------------------------------------------
2180 void SfxMedium::DoBackup_Impl()
2182 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxMedium::DoBackup_Impl" );
2184 // source file name is the logical name of this medium
2185 INetURLObject
aSource( GetURLObject() );
2187 // there is nothing to backup in case source file does not exist
2188 if ( !::utl::UCBContentHelper::IsDocument( aSource
.GetMainURL( INetURLObject::NO_DECODE
) ) )
2191 sal_Bool bSuccess
= sal_False
;
2193 // get path for backups
2194 String aBakDir
= SvtPathOptions().GetBackupPath();
2197 // create content for the parent folder ( = backup folder )
2198 ::ucbhelper::Content aContent
;
2199 Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xEnv
;
2200 if( ::ucbhelper::Content::create( aBakDir
, xEnv
, aContent
) )
2202 // save as ".bak" file
2203 INetURLObject
aDest( aBakDir
);
2204 aDest
.insertName( aSource
.getName() );
2205 aDest
.setExtension( DEFINE_CONST_UNICODE( "bak" ) );
2206 String aFileName
= aDest
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
2208 // create a content for the source file
2209 ::ucbhelper::Content aSourceContent
;
2210 if ( ::ucbhelper::Content::create( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xEnv
, aSourceContent
) )
2214 // do the transfer ( copy source file to backup dir )
2215 bSuccess
= aContent
.transferContent( aSourceContent
,
2216 ::ucbhelper::InsertOperation_COPY
,
2218 NameClash::OVERWRITE
);
2221 pImp
->m_aBackupURL
= aDest
.GetMainURL( INetURLObject::NO_DECODE
);
2222 pImp
->m_bRemoveBackup
= sal_False
;
2225 catch ( ::com::sun::star::uno::Exception
& )
2234 eError
= ERRCODE_SFX_CANTCREATEBACKUP
;
2238 //------------------------------------------------------------------
2239 void SfxMedium::ClearBackup_Impl()
2241 if( pImp
->m_bRemoveBackup
)
2243 // currently a document is always stored in a new medium,
2244 // thus if a backup can not be removed the backup URL should not be cleaned
2245 if ( pImp
->m_aBackupURL
.getLength() )
2247 if ( ::utl::UCBContentHelper::Kill( pImp
->m_aBackupURL
) )
2248 // || !::utl::UCBContentHelper::IsDocument( pImp->m_aBackupURL ) );
2250 pImp
->m_bRemoveBackup
= sal_False
;
2251 pImp
->m_aBackupURL
= ::rtl::OUString();
2256 DBG_ERROR("Couldn't remove backup file!");
2261 pImp
->m_aBackupURL
= ::rtl::OUString();
2264 //----------------------------------------------------------------
2265 void SfxMedium::GetMedium_Impl()
2269 pImp
->bDownloadDone
= sal_False
;
2270 Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler
= GetInteractionHandler();
2272 //TODO/MBA: need support for SID_STREAM
2273 SFX_ITEMSET_ARG( pSet
, pWriteStreamItem
, SfxUnoAnyItem
, SID_STREAM
, sal_False
);
2274 SFX_ITEMSET_ARG( pSet
, pInStreamItem
, SfxUnoAnyItem
, SID_INPUTSTREAM
, sal_False
);
2275 if ( pWriteStreamItem
)
2277 pWriteStreamItem
->GetValue() >>= pImp
->xStream
;
2279 if ( pInStreamItem
)
2280 pInStreamItem
->GetValue() >>= pImp
->xInputStream
;
2282 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2283 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2285 else if ( pInStreamItem
)
2287 pInStreamItem
->GetValue() >>= pImp
->xInputStream
;
2291 uno::Sequence
< beans::PropertyValue
> xProps
;
2295 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aFileName
) )
2297 DBG_ERROR("Physical name not convertable!");
2301 aFileName
= GetName();
2303 // in case the temporary file exists the streams should be initialized from it,
2304 // but the original MediaDescriptor should not be changed
2305 sal_Bool bFromTempFile
= ( pImp
->pTempFile
!= NULL
);
2307 if ( !bFromTempFile
)
2309 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, aFileName
) );
2310 if( !(nStorOpenMode
& STREAM_WRITE
) )
2311 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, TRUE
) );
2312 if (xInteractionHandler
.is())
2313 GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER
, makeAny(xInteractionHandler
) ) );
2316 if ( m_xInputStreamToLoadFrom
.is() )
2318 pImp
->xInputStream
= m_xInputStreamToLoadFrom
;
2319 pImp
->xInputStream
->skipBytes(0);
2321 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
2323 // m_xInputStreamToLoadFrom = 0;
2327 TransformItems( SID_OPENDOC
, *GetItemSet(), xProps
);
2328 comphelper::MediaDescriptor
aMedium( xProps
);
2330 if ( bFromTempFile
)
2332 aMedium
[comphelper::MediaDescriptor::PROP_URL()] <<= ::rtl::OUString( aFileName
);
2333 aMedium
.erase( comphelper::MediaDescriptor::PROP_READONLY() );
2334 aMedium
.addInputStream();
2336 else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
2338 // use the special locking approach only for file URLs
2339 aMedium
.addInputStreamOwnLock();
2342 aMedium
.addInputStream();
2344 // the ReadOnly property set in aMedium is ignored
2345 // the check is done in LockOrigFileOnDemand() for file and non-file URLs
2347 //TODO/MBA: what happens if property is not there?!
2349 aMedium
[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp
->xStream
;
2350 aMedium
[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp
->xInputStream
;
2351 if ( !pImp
->xInputStream
.is() && pImp
->xStream
.is() )
2352 pImp
->xInputStream
= pImp
->xStream
->getInputStream();
2355 if ( !bFromTempFile
)
2357 //TODO/MBA: need support for SID_STREAM
2358 if ( pImp
->xStream
.is() )
2359 GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM
, makeAny( pImp
->xStream
) ) );
2361 GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM
, makeAny( pImp
->xInputStream
) ) );
2365 //TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
2366 if ( !GetError() && !pImp
->xStream
.is() && !pImp
->xInputStream
.is() )
2367 SetError( ERRCODE_IO_ACCESSDENIED
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2371 if ( pImp
->xStream
.is() )
2372 pInStream
= utl::UcbStreamHelper::CreateStream( pImp
->xStream
);
2373 else if ( pImp
->xInputStream
.is() )
2374 pInStream
= utl::UcbStreamHelper::CreateStream( pImp
->xInputStream
);
2377 pImp
->bDownloadDone
= sal_True
;
2378 pImp
->aDoneLink
.ClearPendingCall();
2379 pImp
->aDoneLink
.Call( (void*) GetError() );
2383 //------------------------------------------------------------------
2384 SfxPoolCancelManager_Impl
* SfxMedium::GetCancelManager_Impl() const
2386 return pImp
->GetCancelManager();
2389 //------------------------------------------------------------------
2390 void SfxMedium::SetCancelManager_Impl( SfxPoolCancelManager_Impl
* pMgr
)
2392 pImp
->xCancelManager
= pMgr
;
2395 //----------------------------------------------------------------
2396 void SfxMedium::CancelTransfers()
2398 if( pImp
->xCancelManager
.Is() )
2399 pImp
->xCancelManager
->Cancel();
2402 sal_Bool
SfxMedium::IsRemote()
2407 //------------------------------------------------------------------
2409 void SfxMedium::SetUpdatePickList(sal_Bool bVal
)
2412 pImp
= new SfxMedium_Impl( this );
2413 pImp
->bUpdatePickList
= bVal
;
2415 //------------------------------------------------------------------
2417 sal_Bool
SfxMedium::IsUpdatePickList() const
2419 return pImp
? pImp
->bUpdatePickList
: sal_True
;
2421 //----------------------------------------------------------------
2423 void SfxMedium::SetDoneLink( const Link
& rLink
)
2425 pImp
->aDoneLink
= rLink
;
2428 //----------------------------------------------------------------
2430 void SfxMedium::SetDataAvailableLink( const Link
& rLink
)
2432 pImp
->aAvailableLink
= rLink
;
2435 //----------------------------------------------------------------
2436 void SfxMedium::StartDownload()
2441 void SfxMedium::DownLoad( const Link
& aLink
)
2443 SetDoneLink( aLink
);
2445 if ( pInStream
&& !aLink
.IsSet() )
2447 while( !pImp
->bDownloadDone
)
2448 Application::Yield();
2452 //------------------------------------------------------------------
2453 void SfxMedium::Init_Impl()
2455 Setzt in den Logischen Namen eine gueltige ::com::sun::star::util::URL (Falls zuvor ein Filename
2456 drin war) und setzt den physikalschen Namen auf den Filenamen, falls
2461 Reference
< XOutputStream
> rOutStream
;
2463 // TODO/LATER: handle lifetime of storages
2464 pImp
->bDisposeStorage
= FALSE
;
2466 SFX_ITEMSET_ARG( pSet
, pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, sal_False
);
2467 if ( pSalvageItem
&& !pSalvageItem
->GetValue().Len() )
2469 pSalvageItem
= NULL
;
2470 pSet
->ClearItem( SID_DOC_SALVAGE
);
2473 if( aLogicName
.Len() )
2475 INetURLObject
aUrl( aLogicName
);
2476 INetProtocol eProt
= aUrl
.GetProtocol();
2477 if ( eProt
== INET_PROT_NOT_VALID
)
2479 DBG_ERROR ( "Unknown protocol!" );
2483 if ( aUrl
.HasMark() )
2485 aLogicName
= aUrl
.GetURLNoMark( INetURLObject::NO_DECODE
);
2486 GetItemSet()->Put( SfxStringItem( SID_JUMPMARK
, aUrl
.GetMark() ) );
2489 // try to convert the URL into a physical name - but never change a physical name
2490 // physical name may be set if the logical name is changed after construction
2492 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
), aName
);
2494 DBG_ASSERT( pSalvageItem
, "Suspicious change of logical name!" );
2499 if ( pSalvageItem
&& pSalvageItem
->GetValue().Len() )
2501 aLogicName
= pSalvageItem
->GetValue();
2503 pImp
->m_bSalvageMode
= sal_True
;
2506 // in case output stream is by mistake here
2507 // clear the reference
2508 SFX_ITEMSET_ARG( pSet
, pOutStreamItem
, SfxUnoAnyItem
, SID_OUTPUTSTREAM
, sal_False
);
2510 && ( !( pOutStreamItem
->GetValue() >>= rOutStream
)
2511 || !aLogicName
.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL
) )
2513 pSet
->ClearItem( SID_OUTPUTSTREAM
);
2514 DBG_ERROR( "Unexpected Output stream parameter!\n" );
2517 if ( aLogicName
.Len() )
2519 // if the logic name is set it should be set in MediaDescriptor as well
2520 SFX_ITEMSET_ARG( pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, FALSE
);
2521 if ( !pFileNameItem
)
2523 // let the ItemSet be created if necessary
2524 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, INetURLObject( aLogicName
).GetMainURL( INetURLObject::NO_DECODE
) ) );
2531 //------------------------------------------------------------------
2532 SfxMedium::SfxMedium()
2533 : IMPL_CTOR( sal_False
, 0 ), // bRoot, pURLObj
2537 pImp(new SfxMedium_Impl( this ))
2541 //------------------------------------------------------------------
2543 SfxMedium::SfxMedium( const SfxMedium
& rMedium
, sal_Bool bTemporary
)
2545 IMPL_CTOR( sal_True
, // bRoot, pURLObj
2546 rMedium
.pURLObj
? new INetURLObject(*rMedium
.pURLObj
) : 0 ),
2547 pImp(new SfxMedium_Impl( this ))
2549 bDirect
= rMedium
.IsDirect();
2550 nStorOpenMode
= rMedium
.GetOpenMode();
2552 aName
= rMedium
.aName
;
2554 pImp
->bIsTemp
= bTemporary
;
2555 DBG_ASSERT( ! rMedium
.pImp
->bIsTemp
, "Temporaeres Medium darf nicht kopiert werden" );
2556 aLogicName
= rMedium
.aLogicName
;
2557 pSet
= rMedium
.GetItemSet() ? new SfxItemSet(*rMedium
.GetItemSet()) : 0;
2558 pFilter
= rMedium
.pFilter
;
2561 CreateTempFile( sal_True
);
2564 //------------------------------------------------------------------
2566 void SfxMedium::UseInteractionHandler( BOOL bUse
)
2568 pImp
->bAllowDefaultIntHdl
= bUse
;
2571 //------------------------------------------------------------------
2573 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>
2574 SfxMedium::GetInteractionHandler()
2576 // if interaction isnt allowed explicitly ... return empty reference!
2577 if ( !pImp
->bUseInteractionHandler
)
2578 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2580 // search a possible existing handler inside cached item set
2583 ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
> xHandler
;
2584 SFX_ITEMSET_ARG( pSet
, pHandler
, SfxUnoAnyItem
, SID_INTERACTIONHANDLER
, sal_False
);
2585 if ( pHandler
&& (pHandler
->GetValue() >>= xHandler
) && xHandler
.is() )
2589 // if default interaction isnt allowed explicitly ... return empty reference!
2590 if ( !pImp
->bAllowDefaultIntHdl
)
2591 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2593 // otherwhise return cached default handler ... if it exist.
2594 if ( pImp
->xInteraction
.is() )
2595 return pImp
->xInteraction
;
2597 // create default handler and cache it!
2598 ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> xFactory
= ::comphelper::getProcessServiceFactory();
2599 if ( xFactory
.is() )
2601 pImp
->xInteraction
= ::com::sun::star::uno::Reference
< com::sun::star::task::XInteractionHandler
>( xFactory
->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), ::com::sun::star::uno::UNO_QUERY
);
2602 return pImp
->xInteraction
;
2605 return ::com::sun::star::uno::Reference
< ::com::sun::star::task::XInteractionHandler
>();
2608 //----------------------------------------------------------------
2610 void SfxMedium::SetFilter( const SfxFilter
* pFilterP
, sal_Bool
/*bResetOrig*/ )
2613 pImp
->nFileVersion
= 0;
2615 //----------------------------------------------------------------
2617 const SfxFilter
* SfxMedium::GetOrigFilter( sal_Bool bNotCurrent
) const
2619 return ( pImp
->pOrigFilter
|| bNotCurrent
) ? pImp
->pOrigFilter
: pFilter
;
2621 //----------------------------------------------------------------
2623 void SfxMedium::SetOrigFilter_Impl( const SfxFilter
* pOrigFilter
)
2625 pImp
->pOrigFilter
= pOrigFilter
;
2627 //------------------------------------------------------------------
2629 void SfxMedium::Close()
2631 if ( pImp
->xStorage
.is() )
2633 // don't close the streams if they belong to the
2635 //TODO/MBA: how to?! Do we need the flag?!
2637 const SvStream *pStream = aStorage->GetSvStream();
2638 if ( pStream && pStream == pInStream )
2640 CloseZipStorage_Impl();
2642 pImp->xInputStream = Reference < XInputStream >();
2643 pImp->xLockBytes.Clear();
2645 pSet->ClearItem( SID_INPUTSTREAM );
2646 aStorage->SetDeleteStream( TRUE );
2648 else if ( pStream && pStream == pOutStream )
2651 aStorage->SetDeleteStream( TRUE );
2657 CloseStreams_Impl();
2662 void SfxMedium::CloseAndRelease()
2664 if ( pImp
->xStorage
.is() )
2666 // don't close the streams if they belong to the
2668 //TODO/MBA: how to?! Do we need the flag?!
2670 const SvStream *pStream = aStorage->GetSvStream();
2671 if ( pStream && pStream == pInStream )
2673 CloseZipStorage_Impl();
2675 pImp->xInputStream = Reference < XInputStream >();
2676 pImp->xLockBytes.Clear();
2678 pSet->ClearItem( SID_INPUTSTREAM );
2679 aStorage->SetDeleteStream( TRUE );
2681 else if ( pStream && pStream == pOutStream )
2684 aStorage->SetDeleteStream( TRUE );
2690 CloseAndReleaseStreams_Impl();
2695 void SfxMedium::UnlockFile()
2697 if ( pImp
->m_bLocked
)
2701 pImp
->m_bLocked
= sal_False
;
2702 ::svt::DocumentLockFile
aLockFile( aLogicName
);
2703 // TODO/LATER: A warning could be shown in case the file is not the own one
2704 aLockFile
.RemoveFile();
2706 catch( uno::Exception
& )
2711 void SfxMedium::CloseAndReleaseStreams_Impl()
2713 CloseZipStorage_Impl();
2715 uno::Reference
< io::XInputStream
> xInToClose
= pImp
->xInputStream
;
2716 uno::Reference
< io::XOutputStream
> xOutToClose
;
2717 if ( pImp
->xStream
.is() )
2718 xOutToClose
= pImp
->xStream
->getOutputStream();
2720 // The probably exsisting SvStream wrappers should be closed first
2721 CloseStreams_Impl();
2723 // in case of salvage mode the storage is based on the streams
2724 if ( !pImp
->m_bSalvageMode
)
2728 if ( xInToClose
.is() )
2729 xInToClose
->closeInput();
2730 if ( xOutToClose
.is() )
2731 xOutToClose
->closeOutput();
2733 catch ( uno::Exception
& )
2739 //------------------------------------------------------------------
2740 void SfxMedium::CloseStreams_Impl()
2742 CloseInStream_Impl();
2743 CloseOutStream_Impl();
2746 pSet
->ClearItem( SID_CONTENT
);
2748 pImp
->aContent
= ::ucbhelper::Content();
2751 //------------------------------------------------------------------
2753 void SfxMedium::RefreshName_Impl()
2756 if ( pImp
->aContent
.get().is() )
2758 String aNameP
= pImp
->xAnchor
->GetViewURL();
2759 pImp
->aOrigURL
= aNameP
;
2760 aLogicName
= aNameP
;
2762 if (aLogicName
.Len())
2763 aLogicName
= GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
2769 void SfxMedium::SetIsRemote_Impl()
2771 INetURLObject
aObj( GetName() );
2772 switch( aObj
.GetProtocol() )
2775 case INET_PROT_HTTP
:
2776 case INET_PROT_HTTPS
:
2777 case INET_PROT_POP3
:
2778 case INET_PROT_NEWS
:
2779 case INET_PROT_IMAP
:
2780 // case INET_PROT_OUT:
2782 bRemote
= TRUE
; break;
2784 bRemote
= ( GetName().CompareToAscii( "private:msgid", 13 ) == COMPARE_EQUAL
);
2788 // Da Dateien, die Remote geschrieben werden zur Uebertragung auch
2789 // gelesen werden koennen muessen
2791 nStorOpenMode
|= STREAM_READ
;
2796 void SfxMedium::SetName( const String
& aNameP
, sal_Bool bSetOrigURL
)
2798 if( !pImp
->aOrigURL
.Len() )
2799 pImp
->aOrigURL
= aLogicName
;
2801 pImp
->aOrigURL
= aNameP
;
2802 aLogicName
= aNameP
;
2804 pImp
->aContent
= ::ucbhelper::Content();
2808 //----------------------------------------------------------------
2809 const String
& SfxMedium::GetOrigURL() const
2811 return !pImp
->aOrigURL
.Len() ? (String
&)aLogicName
: pImp
->aOrigURL
;
2814 //----------------------------------------------------------------
2816 void SfxMedium::SetPhysicalName_Impl( const String
& rNameP
)
2818 if ( rNameP
!= aName
)
2820 if( pImp
->pTempFile
)
2822 delete pImp
->pTempFile
;
2823 pImp
->pTempFile
= NULL
;
2826 if ( aName
.Len() || rNameP
.Len() )
2827 pImp
->aContent
= ::ucbhelper::Content();
2830 bTriedStorage
= sal_False
;
2831 pImp
->bIsStorage
= sal_False
;
2835 //------------------------------------------------------------------
2836 void SfxMedium::SetTemporary( sal_Bool bTemp
)
2838 pImp
->bIsTemp
= bTemp
;
2841 //------------------------------------------------------------------
2842 sal_Bool
SfxMedium::IsTemporary() const
2844 return pImp
->bIsTemp
;
2847 //------------------------------------------------------------------
2849 sal_Bool
SfxMedium::Exists( sal_Bool
/*bForceSession*/ )
2851 DBG_ERROR( "Not implemented!" );
2855 //------------------------------------------------------------------
2857 void SfxMedium::ReOpen()
2859 BOOL bUseInteractionHandler
= pImp
->bUseInteractionHandler
;
2860 pImp
->bUseInteractionHandler
= FALSE
;
2862 pImp
->bUseInteractionHandler
= bUseInteractionHandler
;
2865 //------------------------------------------------------------------
2867 void SfxMedium::CompleteReOpen()
2869 // do not use temporary file for reopen and in case of success throw the temporary file away
2870 BOOL bUseInteractionHandler
= pImp
->bUseInteractionHandler
;
2871 pImp
->bUseInteractionHandler
= FALSE
;
2873 ::utl::TempFile
* pTmpFile
= NULL
;
2874 if ( pImp
->pTempFile
)
2876 pTmpFile
= pImp
->pTempFile
;
2877 pImp
->pTempFile
= NULL
;
2885 if ( pImp
->pTempFile
)
2887 pImp
->pTempFile
->EnableKillingFile( sal_True
);
2888 delete pImp
->pTempFile
;
2890 pImp
->pTempFile
= pTmpFile
;
2891 if ( pImp
->pTempFile
)
2892 aName
= pImp
->pTempFile
->GetFileName();
2896 pTmpFile
->EnableKillingFile( sal_True
);
2901 pImp
->bUseInteractionHandler
= bUseInteractionHandler
;
2904 //------------------------------------------------------------------
2905 SfxMedium::SfxMedium
2907 const String
&rName
, StreamMode nOpenMode
, sal_Bool bDirectP
,
2908 const SfxFilter
*pFlt
, SfxItemSet
*pInSet
2910 : IMPL_CTOR( sal_False
, 0 ), // bRoot, pURLObj
2913 pImp(new SfxMedium_Impl( this ))
2916 nStorOpenMode
= nOpenMode
;
2922 SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& aArgs
)
2923 : IMPL_CTOR( sal_False
, 0 ), // bRoot, pURLObj
2926 pImp(new SfxMedium_Impl( this ))
2928 SfxAllItemSet
*pParams
= new SfxAllItemSet( SFX_APP()->GetPool() );
2930 TransformParameters( SID_OPENDOC
, aArgs
, *pParams
);
2933 SFX_ITEMSET_ARG( pSet
, pFilterNameItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
2934 if( pFilterNameItem
)
2935 aFilterName
= pFilterNameItem
->GetValue();
2936 pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4FilterName( aFilterName
);
2938 sal_Bool bSalvage
= sal_False
;
2939 SFX_ITEMSET_ARG( pSet
, pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, sal_False
);
2942 // QUESTION: there is some treatment of Salvage in Init_Impl; align!
2943 bSalvage
= sal_True
;
2944 if ( pSalvageItem
->GetValue().Len() )
2946 // if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
2947 // that must be copied here
2949 SFX_ITEMSET_ARG( pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, FALSE
);
2950 if (!pFileNameItem
) throw uno::RuntimeException();
2951 ::rtl::OUString aNewTempFileURL
= SfxMedium::CreateTempCopyWithExt( pFileNameItem
->GetValue() );
2952 if ( aNewTempFileURL
.getLength() )
2954 pSet
->Put( SfxStringItem( SID_FILE_NAME
, aNewTempFileURL
) );
2955 pSet
->ClearItem( SID_INPUTSTREAM
);
2956 pSet
->ClearItem( SID_STREAM
);
2957 pSet
->ClearItem( SID_CONTENT
);
2961 OSL_ENSURE( sal_False
, "Can not create a new temporary file for crash recovery!\n" );
2966 BOOL bReadOnly
= FALSE
;
2967 SFX_ITEMSET_ARG( pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, FALSE
);
2968 if ( pReadOnlyItem
&& pReadOnlyItem
->GetValue() )
2971 SFX_ITEMSET_ARG( pSet
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, FALSE
);
2972 if (!pFileNameItem
) throw uno::RuntimeException();
2973 aLogicName
= pFileNameItem
->GetValue();
2974 nStorOpenMode
= bReadOnly
? SFX_STREAM_READONLY
: SFX_STREAM_READWRITE
;
2980 //------------------------------------------------------------------
2982 SfxMedium::SfxMedium( const uno::Reference
< embed::XStorage
>& rStor
, const String
& rBaseURL
, const SfxItemSet
* p
, sal_Bool bRootP
)
2983 : IMPL_CTOR( bRootP
, 0 ), // bRoot, pURLObj
2985 pImp( new SfxMedium_Impl( this ))
2987 String aType
= SfxFilter::GetTypeFromStorage( rStor
);
2988 pFilter
= SFX_APP()->GetFilterMatcher().GetFilter4EA( aType
);
2989 DBG_ASSERT( pFilter
, "No Filter for storage found!" );
2992 pImp
->xStorage
= rStor
;
2993 pImp
->bDisposeStorage
= FALSE
;
2995 // always take BaseURL first, could be overwritten by ItemSet
2996 GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, rBaseURL
) );
2998 GetItemSet()->Put( *p
);
3001 //------------------------------------------------------------------
3003 SfxMedium::~SfxMedium()
3006 Don't enable CancelTransfers() till you know that the writer/web has changed his asynchronous load
3007 behaviour. Otherwhise may StyleSheets inside a html file will be loaded at the right time.
3008 => further the help will be empty then ... #100490#
3010 //CancelTransfers();
3012 // if there is a requirement to clean the backup this is the last possibility to do it
3019 if( pImp
->bIsTemp
&& aName
.Len() )
3022 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aTemp
))
3024 DBG_ERROR("Physical name not convertable!");
3027 if ( !::utl::UCBContentHelper::Kill( aTemp
) )
3029 DBG_ERROR("Couldn't remove temporary file!");
3039 //------------------------------------------------------------------
3040 void SfxMedium::SetItemSet(SfxItemSet
*pNewSet
)
3046 //----------------------------------------------------------------
3047 const INetURLObject
& SfxMedium::GetURLObject() const
3051 SfxMedium
* pThis
= const_cast < SfxMedium
* > (this);
3052 pThis
->pURLObj
= new INetURLObject( aLogicName
);
3053 if ( pThis
->pURLObj
->HasMark() )
3054 (*pThis
->pURLObj
) = INetURLObject( aLogicName
).GetURLNoMark();
3060 //----------------------------------------------------------------
3062 const String
& SfxMedium::GetPreRedirectedURL() const
3064 return pImp
->aPreRedirectionURL
;
3066 //----------------------------------------------------------------
3068 sal_uInt32
SfxMedium::GetMIMEAndRedirect( String
& /*rName*/ )
3070 /* dv !!!! not needed any longer ?
3071 INetProtocol eProt = GetURLObject().GetProtocol();
3072 if( eProt == INET_PROT_FTP && SvBinding::ShouldUseFtpProxy( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
3074 Any aAny( UCB_Helper::GetProperty( GetContent(), WID_FLAG_IS_FOLDER ) );
3075 sal_Bool bIsFolder = FALSE;
3076 if ( ( aAny >>= bIsFolder ) && bIsFolder )
3077 return ERRCODE_NONE;
3081 if( !eError && pImp->xBinding.Is() )
3083 eError = pImp->xBinding->GetMimeType( rName );
3085 // Wir koennen keine Parameter wie CharSets usw.
3086 rName = rName.GetToken( 0, ';' );
3089 if( !pImp->aPreRedirectionURL.Len() )
3090 pImp->aPreRedirectionURL = aLogicName;
3091 SetName( pImp->xBinding->GetRedirectedURL() );
3093 pImp->aExpireTime = pImp->xBinding->GetExpireDateTime();
3100 //----------------------------------------------------------------
3102 void SfxMedium::SetReferer( const String
& rRefer
)
3104 pImp
->aReferer
= rRefer
;
3106 //----------------------------------------------------------------
3108 const String
& SfxMedium::GetReferer( ) const
3110 return pImp
->aReferer
;
3113 //----------------------------------------------------------------
3115 void SfxMedium::SetExpired_Impl( const DateTime
& rDateTime
)
3117 pImp
->aExpireTime
= rDateTime
;
3119 //----------------------------------------------------------------
3121 sal_Bool
SfxMedium::IsExpired() const
3123 return pImp
->aExpireTime
.IsValid() && pImp
->aExpireTime
< DateTime();
3125 //----------------------------------------------------------------
3127 void SfxMedium::ForceSynchronStream_Impl( sal_Bool bForce
)
3131 SvLockBytes
* pBytes
= pInStream
->GetLockBytes();
3133 pBytes
->SetSynchronMode( bForce
);
3135 pImp
->bForceSynchron
= bForce
;
3138 //----------------------------------------------------------------
3139 SfxFrame
* SfxMedium::GetLoadTargetFrame() const
3141 return pImp
->wLoadTargetFrame
;
3143 //----------------------------------------------------------------
3145 void SfxMedium::SetLoadTargetFrame(SfxFrame
* pFrame
)
3147 pImp
->wLoadTargetFrame
= pFrame
;
3149 //----------------------------------------------------------------
3151 void SfxMedium::SetStorage_Impl( const uno::Reference
< embed::XStorage
>& rStor
)
3153 pImp
->xStorage
= rStor
;
3155 //----------------------------------------------------------------
3157 SfxItemSet
* SfxMedium::GetItemSet() const
3159 // this method *must* return an ItemSet, returning NULL can cause crashes
3161 ((SfxMedium
*)this)->pSet
= new SfxAllItemSet( SFX_APP()->GetPool() );
3164 //----------------------------------------------------------------
3166 SvKeyValueIterator
* SfxMedium::GetHeaderAttributes_Impl()
3168 if( !pImp
->xAttributes
.Is() )
3170 pImp
->xAttributes
= SvKeyValueIteratorRef( new SvKeyValueIterator
);
3172 if ( GetContent().is() )
3174 pImp
->bIsCharsetInitialized
= sal_True
;
3178 Any aAny
= pImp
->aContent
.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
3179 ::rtl::OUString aContentType
;
3180 aAny
>>= aContentType
;
3182 pImp
->xAttributes
->Append( SvKeyValue( ::rtl::OUString::createFromAscii( "content-type" ), aContentType
) );
3184 catch ( ::com::sun::star::uno::Exception
& )
3190 return pImp
->xAttributes
;
3192 //----------------------------------------------------------------
3194 SvCompatWeakHdl
* SfxMedium::GetHdl()
3196 return pImp
->GetHdl();
3199 sal_Bool
SfxMedium::IsDownloadDone_Impl()
3201 return pImp
->bDownloadDone
;
3204 //----------------------------------------------------------------
3206 void SfxMedium::SetDontCreateCancellable( )
3208 pImp
->bDontCreateCancellable
= sal_True
;
3211 ::com::sun::star::uno::Reference
< ::com::sun::star::io::XInputStream
> SfxMedium::GetInputStream()
3213 if ( !pImp
->xInputStream
.is() )
3215 return pImp
->xInputStream
;
3218 const uno::Sequence
< util::RevisionTag
>& SfxMedium::GetVersionList( bool _bNoReload
)
3220 // if the medium has no name, then this medium should represent a new document and can have no version info
3221 if ( ( !_bNoReload
|| !pImp
->m_bVersionsAlreadyLoaded
) && !pImp
->aVersions
.getLength() &&
3222 ( aName
.Len() || aLogicName
.Len() ) && GetStorage().is() )
3224 uno::Reference
< document::XDocumentRevisionListPersistence
> xReader( comphelper::getProcessServiceFactory()->createInstance(
3225 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY
);
3230 pImp
->aVersions
= xReader
->load( GetStorage() );
3232 catch ( uno::Exception
& )
3238 if ( !pImp
->m_bVersionsAlreadyLoaded
)
3239 pImp
->m_bVersionsAlreadyLoaded
= sal_True
;
3241 return pImp
->aVersions
;
3244 uno::Sequence
< util::RevisionTag
> SfxMedium::GetVersionList( const uno::Reference
< embed::XStorage
>& xStorage
)
3246 uno::Reference
< document::XDocumentRevisionListPersistence
> xReader( comphelper::getProcessServiceFactory()->createInstance(
3247 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY
);
3252 return xReader
->load( xStorage
);
3254 catch ( uno::Exception
& )
3259 return uno::Sequence
< util::RevisionTag
>();
3262 sal_uInt16
SfxMedium::AddVersion_Impl( util::RevisionTag
& rRevision
)
3264 if ( GetStorage().is() )
3266 // Einen eindeutigen Namen f"ur den Stream ermitteln
3268 sal_Int32 nLength
= pImp
->aVersions
.getLength();
3269 for ( sal_Int32 m
=0; m
<nLength
; m
++ )
3271 sal_uInt32 nVer
= (sal_uInt32
) String( pImp
->aVersions
[m
].Identifier
).Copy(7).ToInt32();
3273 for ( n
=0; n
<aLongs
.Count(); n
++ )
3274 if ( nVer
<aLongs
[n
] )
3277 aLongs
.Insert( nVer
, n
);
3281 for ( nKey
=0; nKey
<aLongs
.Count(); nKey
++ )
3282 if ( aLongs
[nKey
] > ( ULONG
) nKey
+1 )
3285 String aRevName
= DEFINE_CONST_UNICODE( "Version" );
3286 aRevName
+= String::CreateFromInt32( nKey
+ 1 );
3287 pImp
->aVersions
.realloc( nLength
+1 );
3288 rRevision
.Identifier
= aRevName
;
3289 pImp
->aVersions
[nLength
] = rRevision
;
3296 sal_Bool
SfxMedium::RemoveVersion_Impl( const ::rtl::OUString
& rName
)
3298 if ( !pImp
->aVersions
.getLength() )
3301 sal_Int32 nLength
= pImp
->aVersions
.getLength();
3302 for ( sal_Int32 n
=0; n
<nLength
; n
++ )
3304 if ( pImp
->aVersions
[n
].Identifier
== rName
)
3306 for ( sal_Int32 m
=n
; m
<nLength
-1; m
++ )
3307 pImp
->aVersions
[m
] = pImp
->aVersions
[m
+1];
3308 pImp
->aVersions
.realloc(nLength
-1);
3316 sal_Bool
SfxMedium::TransferVersionList_Impl( SfxMedium
& rMedium
)
3318 if ( rMedium
.pImp
->aVersions
.getLength() )
3320 pImp
->aVersions
= rMedium
.pImp
->aVersions
;
3327 sal_Bool
SfxMedium::SaveVersionList_Impl( sal_Bool
/*bUseXML*/ )
3329 if ( GetStorage().is() )
3331 if ( !pImp
->aVersions
.getLength() )
3334 uno::Reference
< document::XDocumentRevisionListPersistence
> xWriter( comphelper::getProcessServiceFactory()->createInstance(
3335 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY
);
3340 xWriter
->store( GetStorage(), pImp
->aVersions
);
3343 catch ( uno::Exception
& )
3352 //----------------------------------------------------------------
3353 sal_Bool
SfxMedium::IsReadOnly()
3355 sal_Bool bReadOnly
= sal_False
;
3357 // a) ReadOnly filter cant produce read/write contents!
3360 ((pFilter
->GetFilterFlags() & SFX_FILTER_OPENREADONLY
) == SFX_FILTER_OPENREADONLY
)
3363 // b) if filter allow read/write contents .. check open mode of the storage
3365 bReadOnly
= !( GetOpenMode() & STREAM_WRITE
);
3367 // c) the API can force the readonly state!
3370 SFX_ITEMSET_ARG( GetItemSet(), pItem
, SfxBoolItem
, SID_DOC_READONLY
, sal_False
);
3372 bReadOnly
= pItem
->GetValue();
3378 //----------------------------------------------------------------
3379 sal_Bool
SfxMedium::SetWritableForUserOnly( const ::rtl::OUString
& aURL
)
3381 // UCB does not allow to allow write access only for the user,
3383 sal_Bool bResult
= sal_False
;
3385 ::osl::DirectoryItem aDirItem
;
3386 if ( ::osl::DirectoryItem::get( aURL
, aDirItem
) == ::osl::FileBase::E_None
)
3388 ::osl::FileStatus
aFileStatus( FileStatusMask_Attributes
);
3389 if ( aDirItem
.getFileStatus( aFileStatus
) == osl::FileBase::E_None
3390 && aFileStatus
.isValid( FileStatusMask_Attributes
) )
3392 sal_uInt64 nAttributes
= aFileStatus
.getAttributes();
3394 nAttributes
&= ~(Attribute_OwnWrite
|
3395 Attribute_GrpWrite
|
3396 Attribute_OthWrite
|
3397 Attribute_ReadOnly
);
3398 nAttributes
|= Attribute_OwnWrite
;
3400 bResult
= ( osl::File::setAttributes( aURL
, nAttributes
) == ::osl::FileBase::E_None
);
3407 //----------------------------------------------------------------
3408 void SfxMedium::CreateTempFile( sal_Bool bReplace
)
3410 if ( pImp
->pTempFile
)
3415 DELETEZ( pImp
->pTempFile
);
3419 pImp
->pTempFile
= new ::utl::TempFile();
3420 pImp
->pTempFile
->EnableKillingFile( sal_True
);
3421 aName
= pImp
->pTempFile
->GetFileName();
3422 ::rtl::OUString aTmpURL
= pImp
->pTempFile
->GetURL();
3423 if ( !aName
.Len() || !aTmpURL
.getLength() )
3425 SetError( ERRCODE_IO_CANTWRITE
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
3429 if ( !( nStorOpenMode
& STREAM_TRUNC
) )
3431 if ( GetContent().is()
3432 && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) )
3433 && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE
) ) )
3435 // if there is already such a document, we should copy it
3436 // if it is a file system use OS copy process
3437 sal_Bool bTransferSuccess
= sal_False
;
3440 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
3441 INetURLObject
aTmpURLObj( aTmpURL
);
3442 ::rtl::OUString aFileName
= aTmpURLObj
.getName( INetURLObject::LAST_SEGMENT
,
3444 INetURLObject::DECODE_WITH_CHARSET
);
3445 if ( aFileName
.getLength() && aTmpURLObj
.removeSegment() )
3447 ::ucbhelper::Content
aTargetContent( aTmpURLObj
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
3448 if ( aTargetContent
.transferContent( pImp
->aContent
, ::ucbhelper::InsertOperation_COPY
, aFileName
, NameClash::OVERWRITE
) )
3450 SetWritableForUserOnly( aTmpURL
);
3451 bTransferSuccess
= sal_True
;
3455 catch( uno::Exception
& )
3458 if ( !bTransferSuccess
)
3460 SetError( ERRCODE_IO_CANTWRITE
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
3467 else if ( pInStream
)
3469 // the case when there is no URL-access available or this is a remote protocoll
3470 // but there is an input stream
3474 char *pBuf
= new char [8192];
3475 sal_uInt32 nErr
= ERRCODE_NONE
;
3478 pOutStream
->Seek(0);
3480 while( !pInStream
->IsEof() && nErr
== ERRCODE_NONE
)
3482 sal_uInt32 nRead
= pInStream
->Read( pBuf
, 8192 );
3483 nErr
= pInStream
->GetError();
3484 pOutStream
->Write( pBuf
, nRead
);
3490 CloseOutStream_Impl();
3499 //----------------------------------------------------------------
3500 void SfxMedium::CreateTempFileNoCopy()
3502 // this call always replaces the existing temporary file
3503 if ( pImp
->pTempFile
)
3504 delete pImp
->pTempFile
;
3506 pImp
->pTempFile
= new ::utl::TempFile();
3507 pImp
->pTempFile
->EnableKillingFile( sal_True
);
3508 aName
= pImp
->pTempFile
->GetFileName();
3511 SetError( ERRCODE_IO_CANTWRITE
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
3515 CloseOutStream_Impl();
3519 ::rtl::OUString
SfxMedium::GetCharset()
3521 if( !pImp
->bIsCharsetInitialized
)
3523 // Set an error in case there is no content?
3524 if ( GetContent().is() )
3526 pImp
->bIsCharsetInitialized
= sal_True
;
3530 Any aAny
= pImp
->aContent
.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
3531 ::rtl::OUString aField
;
3534 ::rtl::OString sContent
= ::rtl::OUStringToOString( aField
, RTL_TEXTENCODING_ASCII_US
);
3535 ByteString sType
, sSubType
;
3536 INetContentTypeParameterList aParameters
;
3538 if( INetContentTypes::parse( sContent
, sType
, sSubType
, &aParameters
) )
3540 const INetContentTypeParameter
* pCharset
= aParameters
.find("charset");
3542 pImp
->aCharset
= pCharset
->m_sValue
;
3545 catch ( ::com::sun::star::uno::Exception
& )
3551 return pImp
->aCharset
;
3554 void SfxMedium::SetCharset( ::rtl::OUString aChs
)
3556 pImp
->bIsCharsetInitialized
= sal_True
;
3557 pImp
->aCharset
= aChs
;
3560 sal_Bool
SfxMedium::SignContents_Impl( sal_Bool bScriptingContent
, const ::rtl::OUString
& aODFVersion
, sal_Bool bHasValidDocumentSignature
)
3562 sal_Bool bChanges
= FALSE
;
3564 // the medium should be closed to be able to sign, the caller is responsible to close it
3565 if ( !IsOpen() && !GetError() )
3567 // The component should know if there was a valid document signature, since
3568 // it should show a warning in this case
3569 uno::Sequence
< uno::Any
> aArgs( 2 );
3570 aArgs
[0] <<= aODFVersion
;
3571 aArgs
[1] <<= bHasValidDocumentSignature
;
3572 ::com::sun::star::uno::Reference
< ::com::sun::star::security::XDocumentDigitalSignatures
> xSigner(
3573 comphelper::getProcessServiceFactory()->createInstanceWithArguments(
3574 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ),
3576 ::com::sun::star::uno::UNO_QUERY
);
3580 uno::Reference
< embed::XStorage
> xWriteableZipStor
;
3581 if ( !IsReadOnly() )
3583 // we can reuse the temporary file if there is one already
3584 CreateTempFile( sal_False
);
3589 if ( !pImp
->xStream
.is() )
3590 throw uno::RuntimeException();
3592 xWriteableZipStor
= ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING
, pImp
->xStream
);
3593 if ( !xWriteableZipStor
.is() )
3594 throw uno::RuntimeException();
3596 uno::Reference
< embed::XStorage
> xMetaInf
= xWriteableZipStor
->openStorageElement(
3597 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
3598 embed::ElementModes::READWRITE
);
3599 if ( !xMetaInf
.is() )
3600 throw uno::RuntimeException();
3602 if ( bScriptingContent
)
3604 // If the signature has already the document signature it will be removed
3605 // after the scripting signature is inserted.
3606 uno::Reference
< io::XStream
> xStream(
3607 xMetaInf
->openStreamElement( xSigner
->getScriptingContentSignatureDefaultStreamName(),
3608 embed::ElementModes::READWRITE
),
3609 uno::UNO_SET_THROW
);
3611 if ( xSigner
->signScriptingContent( GetZipStorageToSign_Impl(), xStream
) )
3613 // remove the document signature if any
3614 ::rtl::OUString aDocSigName
= xSigner
->getDocumentContentSignatureDefaultStreamName();
3615 if ( aDocSigName
.getLength() && xMetaInf
->hasByName( aDocSigName
) )
3616 xMetaInf
->removeElement( aDocSigName
);
3618 uno::Reference
< embed::XTransactedObject
> xTransact( xMetaInf
, uno::UNO_QUERY_THROW
);
3619 xTransact
->commit();
3620 xTransact
.set( xWriteableZipStor
, uno::UNO_QUERY_THROW
);
3621 xTransact
->commit();
3623 // the temporary file has been written, commit it to the original file
3630 uno::Reference
< io::XStream
> xStream(
3631 xMetaInf
->openStreamElement( xSigner
->getDocumentContentSignatureDefaultStreamName(),
3632 embed::ElementModes::READWRITE
),
3633 uno::UNO_SET_THROW
);
3635 if ( xSigner
->signDocumentContent( GetZipStorageToSign_Impl(), xStream
) )
3637 uno::Reference
< embed::XTransactedObject
> xTransact( xMetaInf
, uno::UNO_QUERY_THROW
);
3638 xTransact
->commit();
3639 xTransact
.set( xWriteableZipStor
, uno::UNO_QUERY_THROW
);
3640 xTransact
->commit();
3642 // the temporary file has been written, commit it to the original file
3648 catch ( uno::Exception
& )
3650 OSL_ENSURE( sal_False
, "Couldn't use signing functionality!\n" );
3659 if ( bScriptingContent
)
3660 xSigner
->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference
< io::XInputStream
>() );
3662 xSigner
->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference
< io::XInputStream
>() );
3664 catch( uno::Exception
& )
3666 OSL_ENSURE( sal_False
, "Couldn't use signing functionality!\n" );
3677 //----------------------------------------------------------------
3678 sal_uInt16
SfxMedium::GetCachedSignatureState_Impl()
3680 return pImp
->m_nSignatureState
;
3683 //----------------------------------------------------------------
3684 void SfxMedium::SetCachedSignatureState_Impl( sal_uInt16 nState
)
3686 pImp
->m_nSignatureState
= nState
;
3689 //----------------------------------------------------------------
3690 sal_Bool
SfxMedium::EqualURLs( const ::rtl::OUString
& aFirstURL
, const ::rtl::OUString
& aSecondURL
)
3692 sal_Bool bResult
= sal_False
;
3694 if ( aFirstURL
.getLength() && aSecondURL
.getLength() )
3696 INetURLObject
aFirst( aFirstURL
);
3697 INetURLObject
aSecond( aSecondURL
);
3699 if ( aFirst
.GetProtocol() != INET_PROT_NOT_VALID
&& aSecond
.GetProtocol() != INET_PROT_NOT_VALID
)
3703 ::ucbhelper::ContentBroker
* pBroker
= ::ucbhelper::ContentBroker::get();
3705 throw uno::RuntimeException();
3707 uno::Reference
< ::com::sun::star::ucb::XContentIdentifierFactory
> xIdFac
3708 = pBroker
->getContentIdentifierFactoryInterface();
3710 throw uno::RuntimeException();
3712 uno::Reference
< ::com::sun::star::ucb::XContentIdentifier
> xIdFirst
3713 = xIdFac
->createContentIdentifier( aFirst
.GetMainURL( INetURLObject::NO_DECODE
) );
3714 uno::Reference
< ::com::sun::star::ucb::XContentIdentifier
> xIdSecond
3715 = xIdFac
->createContentIdentifier( aSecond
.GetMainURL( INetURLObject::NO_DECODE
) );
3717 if ( xIdFirst
.is() && xIdSecond
.is() )
3719 uno::Reference
< ::com::sun::star::ucb::XContentProvider
> xProvider
=
3720 pBroker
->getContentProviderInterface();
3721 if ( !xProvider
.is() )
3722 throw uno::RuntimeException();
3723 bResult
= !xProvider
->compareContentIds( xIdFirst
, xIdSecond
);
3726 catch( uno::Exception
& )
3728 OSL_ENSURE( sal_False
, "Can't compare URL's, treat as different!\n" );
3736 BOOL
SfxMedium::HasStorage_Impl() const
3738 return pImp
->xStorage
.is();
3741 BOOL
SfxMedium::IsOpen() const
3743 return pInStream
|| pOutStream
|| pImp
->xStorage
.is();
3746 ::rtl::OUString
SfxMedium::CreateTempCopyWithExt( const ::rtl::OUString
& aURL
)
3748 ::rtl::OUString aResult
;
3750 if ( aURL
.getLength() )
3752 sal_Int32 nPrefixLen
= aURL
.lastIndexOf( '.' );
3753 String aExt
= ( nPrefixLen
== -1 ) ? String() : String( aURL
.copy( nPrefixLen
) );
3755 ::rtl::OUString aNewTempFileURL
= ::utl::TempFile( String(), &aExt
).GetURL();
3756 if ( aNewTempFileURL
.getLength() )
3758 INetURLObject
aSource( aURL
);
3759 INetURLObject
aDest( aNewTempFileURL
);
3760 ::rtl::OUString aFileName
= aDest
.getName( INetURLObject::LAST_SEGMENT
,
3762 INetURLObject::DECODE_WITH_CHARSET
);
3763 if ( aFileName
.getLength() && aDest
.removeSegment() )
3767 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xComEnv
;
3768 ::ucbhelper::Content
aTargetContent( aDest
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
3769 ::ucbhelper::Content
aSourceContent( aSource
.GetMainURL( INetURLObject::NO_DECODE
), xComEnv
);
3770 if ( aTargetContent
.transferContent( aSourceContent
,
3771 ::ucbhelper::InsertOperation_COPY
,
3773 NameClash::OVERWRITE
) )
3776 aResult
= aNewTempFileURL
;
3779 catch( uno::Exception
& )
3788 sal_Bool
SfxMedium::CallApproveHandler( const uno::Reference
< task::XInteractionHandler
>& xHandler
, uno::Any aRequest
, sal_Bool bAllowAbort
)
3790 sal_Bool bResult
= sal_False
;
3792 if ( xHandler
.is() )
3796 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > aContinuations( bAllowAbort
? 2 : 1 );
3798 ::rtl::Reference
< ::framework::ContinuationApprove
> pApprove( new ::framework::ContinuationApprove() );
3799 aContinuations
[ 0 ] = pApprove
.get();
3803 ::rtl::Reference
< ::framework::ContinuationAbort
> pAbort( new ::framework::ContinuationAbort() );
3804 aContinuations
[ 1 ] = pAbort
.get();
3807 uno::Reference
< task::XInteractionRequest
> xRequest( new ::framework::InteractionRequest( aRequest
, aContinuations
) );
3808 xHandler
->handle( xRequest
);
3810 bResult
= pApprove
->isSelected();
3812 catch( const Exception
& )
3820 ::rtl::OUString
SfxMedium::SwitchDocumentToTempFile()
3822 // the method returns empty string in case of failure
3823 ::rtl::OUString aResult
;
3824 ::rtl::OUString aOrigURL
= aLogicName
;
3826 if ( aOrigURL
.getLength() )
3828 sal_Int32 nPrefixLen
= aOrigURL
.lastIndexOf( '.' );
3829 String aExt
= ( nPrefixLen
== -1 ) ? String() : String( aOrigURL
.copy( nPrefixLen
) );
3830 ::rtl::OUString aNewURL
= ::utl::TempFile( String(), &aExt
).GetURL();
3832 // TODO/LATER: In future the aLogicName should be set to shared folder URL
3833 // and a temporary file should be created. Transport_Impl should be impossible then.
3834 if ( aNewURL
.getLength() )
3836 uno::Reference
< embed::XStorage
> xStorage
= GetStorage();
3837 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY
);
3839 if ( xOptStorage
.is() )
3841 // TODO/LATER: reuse the pImp->pTempFile if it already exists
3842 CanDisposeStorage_Impl( sal_False
);
3844 SetPhysicalName_Impl( String() );
3847 // remove the readonly state
3848 sal_Bool bWasReadonly
= sal_False
;
3849 nStorOpenMode
= SFX_STREAM_READWRITE
;
3850 SFX_ITEMSET_ARG( pSet
, pReadOnlyItem
, SfxBoolItem
, SID_DOC_READONLY
, FALSE
);
3851 if ( pReadOnlyItem
&& pReadOnlyItem
->GetValue() )
3852 bWasReadonly
= sal_True
;
3853 GetItemSet()->ClearItem( SID_DOC_READONLY
);
3856 LockOrigFileOnDemand( sal_False
, sal_False
);
3857 CreateTempFile( sal_True
);
3860 if ( pImp
->xStream
.is() )
3864 xOptStorage
->writeAndAttachToStream( pImp
->xStream
);
3865 pImp
->xStorage
= xStorage
;
3868 catch( uno::Exception
& )
3872 if ( !aResult
.getLength() )
3875 SetPhysicalName_Impl( String() );
3876 SetName( aOrigURL
);
3879 // set the readonly state back
3880 nStorOpenMode
= SFX_STREAM_READONLY
;
3881 GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY
, sal_True
));
3884 pImp
->xStorage
= xStorage
;
3893 sal_Bool
SfxMedium::SwitchDocumentToFile( ::rtl::OUString aURL
)
3895 // the method is only for storage based documents
3896 sal_Bool bResult
= sal_False
;
3897 ::rtl::OUString aOrigURL
= aLogicName
;
3899 if ( aURL
.getLength() && aOrigURL
.getLength() )
3901 uno::Reference
< embed::XStorage
> xStorage
= GetStorage();
3902 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY
);
3904 if ( xOptStorage
.is() )
3906 // TODO/LATER: reuse the pImp->pTempFile if it already exists
3907 CanDisposeStorage_Impl( sal_False
);
3909 SetPhysicalName_Impl( String() );
3912 // open the temporary file based document
3914 LockOrigFileOnDemand( sal_False
, sal_False
);
3915 CreateTempFile( sal_True
);
3918 if ( pImp
->xStream
.is() )
3922 uno::Reference
< io::XTruncate
> xTruncate( pImp
->xStream
, uno::UNO_QUERY_THROW
);
3923 if ( xTruncate
.is() )
3924 xTruncate
->truncate();
3926 xOptStorage
->writeAndAttachToStream( pImp
->xStream
);
3927 pImp
->xStorage
= xStorage
;
3930 catch( uno::Exception
& )
3937 SetPhysicalName_Impl( String() );
3938 SetName( aOrigURL
);
3940 pImp
->xStorage
= xStorage
;