merge the formfield patch from ooo-build
[ooovba.git] / sfx2 / source / doc / docfile.cxx
blob559fc4485362807460ecb5d7a7b7e9fc48b42d12
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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>
79 #endif
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>
92 #endif
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
148 #include "doc.hrc"
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 //==========================================================
159 namespace {
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(
181 xCommonConfig,
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(
208 xCommonConfig,
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;
228 public:
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 )
248 if( !m_xInter.is() )
249 return;
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 ) )
255 return;
256 else
257 if ( aRequest >>= aSinkException )
258 return;
259 else
260 m_xInter->handle( xRequest );
263 //----------------------------------------------------------------
264 class SfxPoolCancelManager_Impl : public SfxCancelManager ,
265 public SfxCancellable ,
266 public SfxListener ,
267 public SvRefBase
269 SfxCancelManagerWeak wParent;
271 ~SfxPoolCancelManager_Impl();
272 public:
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 ),
288 wParent( pParent )
290 if( pParent )
292 StartListening( *this );
293 SetManager( 0 );
297 //----------------------------------------------------------------
298 SfxPoolCancelManager_Impl::~SfxPoolCancelManager_Impl()
300 for( sal_uInt16 nPos = GetCancellableCount(); nPos--; )
302 // nicht an Parent uebernehmen!
303 SfxCancellable* pCbl = GetCancellable( nPos );
304 if ( pCbl )
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 )
330 pCbl->Cancel();
331 if( GetCancellableCount() < nPos )
332 nPos = GetCancellableCount();
336 //----------------------------------------------------------------
337 class SfxMedium_Impl : public SvCompatWeakBase
339 public:
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;
363 long nFileVersion;
365 const SfxFilter* pOrigFilter;
366 String aOrigURL;
367 String aPreRedirectionURL;
368 String aReferer;
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 );
404 ~SfxMedium_Impl();
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() );
427 else
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 ),
453 nFileVersion( 0 ),
454 pOrigFilter( 0 ),
455 aExpireTime( Date() + 10, Time() ),
456 pTempFile( NULL ),
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();
471 if ( pTempFile )
472 delete pTempFile;
475 //================================================================
477 #define IMPL_CTOR(rootVal,URLVal) \
478 eError( SVSTREAM_OK ), \
480 bDirect( sal_False ), \
481 bRoot( rootVal ), \
482 bSetFilter( sal_False ), \
483 bTriedStorage( sal_False ), \
485 nStorOpenMode( SFX_STREAM_READWRITE ), \
486 pURLObj( URLVal ), \
487 pInStream(0), \
488 pOutStream( 0 )
490 //------------------------------------------------------------------
491 void SfxMedium::ResetError()
493 eError = SVSTREAM_OK;
494 if( pInStream )
495 pInStream->ResetError();
496 if( pOutStream )
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() );
514 if ( aContext.is() )
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 )
528 eError = nError;
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();
541 return lError;
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();
557 if ( xHandler.is() )
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);
615 if ( pItem )
616 pItem->GetValue() >>= xContent;
618 if ( xContent.is() )
622 pImp->aContent = ::ucbhelper::Content( xContent, xEnv );
624 catch ( Exception& )
628 else
630 // TODO: DBG_ERROR("SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
631 String aURL;
632 if ( aName.Len() )
633 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL );
634 else if ( aLogicName.Len() )
635 aURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
636 if ( aURL.Len() )
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) );
649 if ( pBaseURLItem )
650 aBaseURL = pBaseURLItem->GetValue();
651 else if ( GetContent().is() )
655 Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI" )) );
656 aAny >>= aBaseURL;
658 catch ( ::com::sun::star::uno::Exception& )
662 if ( !aBaseURL.getLength() )
663 aBaseURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
666 if ( bForSaving )
668 SvtSaveOptions aOpt;
669 sal_Bool bIsRemote = IsRemote();
670 if( (bIsRemote && !aOpt.IsSaveRelINet()) || (!bRemote && !aOpt.IsSaveRelFSys()) )
671 return ::rtl::OUString();
674 return aBaseURL;
677 //------------------------------------------------------------------
678 SvStream* SfxMedium::GetInStream()
680 if ( pInStream )
681 return pInStream;
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;
693 delete pInStream;
694 pInStream = NULL;
696 else
697 return pInStream;
700 GetMedium_Impl();
702 if ( GetError() )
703 return NULL;
705 return pInStream;
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 )
722 CloseStorage();
725 if ( pInStream && !GetContent().is() )
727 CreateTempFile( sal_True );
728 return;
731 DELETEZ( pInStream );
732 if ( pSet )
733 pSet->ClearItem( SID_INPUTSTREAM );
735 CloseZipStorage_Impl();
736 pImp->xInputStream = uno::Reference< io::XInputStream >();
738 if ( !pOutStream )
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 >();
743 if ( pSet )
744 pSet->ClearItem( SID_STREAM );
748 //------------------------------------------------------------------
749 SvStream* SfxMedium::GetOutStream()
751 if ( !pOutStream )
753 // Create a temp. file if there is none because we always
754 // need one.
755 CreateTempFile( sal_False );
757 if ( pImp->pTempFile )
759 pOutStream = new SvFileStream( aName, STREAM_STD_READWRITE );
760 CloseStorage();
764 return pOutStream;
767 //------------------------------------------------------------------
768 sal_Bool SfxMedium::CloseOutStream()
770 CloseOutStream_Impl();
771 return sal_True;
774 sal_Bool SfxMedium::CloseOutStream_Impl()
776 if ( pOutStream )
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 )
787 CloseStorage();
790 delete pOutStream;
791 pOutStream = NULL;
794 if ( !pInStream )
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 >();
799 if ( pSet )
800 pSet->ClearItem( SID_STREAM );
803 return sal_True;
806 //------------------------------------------------------------------
807 const String& SfxMedium::GetPhysicalName() const
809 if ( !aName.Len() && aLogicName.Len() )
810 (( SfxMedium*)this)->CreateFileStream();
812 // return the name then
813 return aName;
816 //------------------------------------------------------------------
817 void SfxMedium::CreateFileStream()
819 ForceSynchronStream_Impl( TRUE );
820 GetInStream();
821 if( pInStream )
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 )
835 pOutStream->Flush();
836 else if( pInStream )
837 pInStream->Flush();
839 if ( GetError() == SVSTREAM_OK )
841 // does something only in case there is a temporary file ( means aName points to different location than aLogicName )
842 Transfer_Impl();
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);
852 return bResult;
855 //------------------------------------------------------------------
856 sal_Bool SfxMedium::IsStorage()
858 if ( pImp->xStorage.is() )
859 return TRUE;
861 if ( bTriedStorage )
862 return pImp->bIsStorage;
864 if ( pImp->pTempFile )
866 String aURL;
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);
902 if ( pPreview )
903 bPreview = pPreview->GetValue();
904 else
906 SFX_ITEMSET_ARG( GetItemSet(), pFlags, SfxStringItem, SID_OPTIONS, sal_False);
907 if ( pFlags )
909 String aFileFlags = pFlags->GetValue();
910 aFileFlags.ToUpperAscii();
911 if ( STRING_NOTFOUND != aFileFlags.Search( 'B' ) )
912 bPreview = sal_True;
916 return bPreview;
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()
951 if ( GetError() )
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() )
961 CloseInStream();
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();
970 return GetStorage();
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;
1010 if ( bOwnLock )
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 ) ) );
1018 else
1020 if ( aData.getLength() > LOCKFILE_EDITTIME_ID )
1022 if ( aData[LOCKFILE_OOOUSERNAME_ID].getLength() )
1023 aInfo = aData[LOCKFILE_OOOUSERNAME_ID];
1024 else
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( " )" ) );
1035 if ( bIsLoading )
1037 xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
1038 document::LockedDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
1040 else
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
1082 if ( bIsLoading )
1083 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1084 else
1085 nResult = LOCK_UI_TRY;
1088 else
1090 if ( bIsLoading )
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 ) );
1097 else
1098 SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1102 return nResult;
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;
1114 if ( !bResult )
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
1130 GetMedium_Impl();
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
1158 if ( bLoading )
1160 // let the stream be opened to check the system file locking
1161 GetMedium_Impl();
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() )
1190 bResult = sal_True;
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() )
1222 bResult = sal_True;
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() )
1232 bResult = sal_True;
1233 // take the ownership over the lock file
1234 aLockFile.OverwriteOwnLockFile();
1239 if ( !bResult )
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] ) );
1258 if ( bOwnLock
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
1263 bResult = sal_True;
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;
1287 else
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 ) ) );
1303 else
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 );
1311 return bResult;
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
1324 GetMedium_Impl();
1326 if ( bCreateTempIfNo )
1327 CreateTempFile( sal_False );
1329 GetMedium_Impl();
1331 if ( GetError() )
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 );
1339 GetMedium_Impl();
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
1356 aArgs.realloc( 3 );
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;
1374 else
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 ),
1386 uno::UNO_QUERY );
1388 catch( uno::Exception& )
1390 // impossibility to create the storage is no error
1393 if( ( pImp->nLastStorageError = GetError() ) != SVSTREAM_OK )
1395 pImp->xStorage = 0;
1396 if ( pInStream )
1397 pInStream->Seek(0);
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();
1407 GetVersionList();
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;
1423 if ( nVersion<0 )
1424 nVersion = ( (short) pImp->aVersions.getLength() ) + nVersion;
1425 else if ( nVersion )
1426 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;
1447 aTmpStream.Close();
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;
1453 String aTemp;
1454 ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName, aTemp );
1455 SetPhysicalName_Impl( aTemp );
1457 pImp->bIsTemp = sal_True;
1458 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1459 // TODO/MBA
1460 pImp->aVersions.realloc(0);
1462 else
1463 bResetStorage = TRUE;
1466 else
1467 bResetStorage = TRUE;
1470 if ( bResetStorage )
1472 pImp->xStorage = 0;
1473 if ( pInStream )
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() )
1486 // very careful!!!
1487 // if bReadOnly == sal_False and there is no temporary file the original file might be used
1488 GetMedium_Impl();
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
1509 ResetError();
1512 return pImp->m_xZipStorage;
1515 //------------------------------------------------------------------
1516 void SfxMedium::CloseZipStorage_Impl()
1518 if ( pImp->m_xZipStorage.is() )
1520 try {
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 )
1538 try {
1539 xComp->dispose();
1540 } catch( uno::Exception& )
1542 OSL_ENSURE( sal_False, "Medium's storage is already disposed!\n" );
1546 pImp->xStorage = 0;
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,
1566 sal_Bool bDirectP,
1567 sal_Bool bDontClose )
1569 if ( nStorOpenMode != nStorOpen )
1571 nStorOpenMode = nStorOpen;
1573 if( !bDontClose )
1575 if ( pImp->xStorage.is() )
1576 CloseStorage();
1578 CloseStreams_Impl();
1582 bDirect = bDirectP;
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 );
1596 return sal_True;
1598 catch( Exception& )
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;
1607 return sal_False;
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() )
1619 if ( !GetError() )
1621 uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
1622 if ( xTrans.is() )
1626 xTrans->commit();
1627 CloseZipStorage_Impl();
1628 bResult = sal_True;
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 ),
1638 xDummyEnv,
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" );
1653 if ( !GetError() )
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 ) ) );
1666 return bResult;
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;
1694 if (
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() )
1710 CloseStorage();
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 );
1737 bResult = sal_True;
1739 else
1741 eError = ERRCODE_SFX_CANTCREATEBACKUP;
1744 else
1746 Reference< XInputStream > aTempInput = aTempCont.openStream();
1747 aOriginalContent.writeStream( aTempInput, bOverWrite );
1748 bResult = sal_True;
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;
1767 else
1768 eError = ERRCODE_IO_GENERAL;
1770 catch ( ::com::sun::star::uno::Exception& )
1772 eError = ERRCODE_IO_GENERAL;
1775 if ( bResult )
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 );
1789 else
1790 eError = ERRCODE_IO_CANTREAD;
1793 return bResult;
1796 //------------------------------------------------------------------
1797 sal_Bool SfxMedium::TryDirectTransfer( const ::rtl::OUString& aURL, SfxItemSet& aTargetSet )
1799 if ( GetError() )
1800 return sal_False;
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();
1819 ResetError();
1820 if ( xInStream.is() )
1824 uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
1825 sal_Int64 nPos = 0;
1826 if ( xSeek.is() )
1828 nPos = xSeek->getPosition();
1829 xSeek->seek( 0 );
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;
1842 else
1843 aInsertArg.ReplaceExisting = sal_True; // default is overwrite existing files
1845 Any aCmdArg;
1846 aCmdArg <<= aInsertArg;
1847 aTargetContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
1848 aCmdArg );
1850 if ( xSeek.is() )
1851 xSeek->seek( nPos );
1853 return sal_True;
1855 catch( uno::Exception& )
1861 return sal_False;
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
1868 String aNameURL;
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() )
1894 CloseStorage();
1896 CloseStreams_Impl();
1898 INetURLObject aSource( aNameURL );
1899 ::ucbhelper::Content aTempCont;
1900 if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aTempCont ) )
1904 sal_Int32 nRead;
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 );
1917 else
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;
1930 catch( Exception& )
1934 else
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
1941 if ( pSet )
1942 pSet->ClearItem( SID_OUTPUTSTREAM );
1944 return;
1947 GetContent();
1948 if ( !pImp->aContent.get().is() )
1950 eError = ERRCODE_IO_NOTEXISTS;
1951 return;
1954 SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize, SfxInt32Item, SID_SEGMENTSIZE, sal_False);
1955 if ( pSegmentSize )
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
1964 // into this size
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 );
1974 if ( xTrans.is() )
1975 xTrans->commit();
1978 catch ( uno::Exception& )
1980 //TODO/MBA: error handling
1982 return;
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 );
2002 else
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;
2020 if (
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() )
2037 CloseStorage();
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;
2053 else
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;
2078 else
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 ),
2094 aName );
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
2116 // file name...
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,
2134 aBackupName,
2135 NameClash::OVERWRITE ) )
2137 pImp->m_aBackupURL = aBackupURL;
2138 pImp->m_bRemoveBackup = sal_True;
2141 catch( Exception& )
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,
2153 true,
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 ) ) )
2189 return;
2191 sal_Bool bSuccess = sal_False;
2193 // get path for backups
2194 String aBakDir = SvtPathOptions().GetBackupPath();
2195 if( aBakDir.Len() )
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,
2217 aFileName,
2218 NameClash::OVERWRITE );
2219 if( bSuccess )
2221 pImp->m_aBackupURL = aDest.GetMainURL( INetURLObject::NO_DECODE );
2222 pImp->m_bRemoveBackup = sal_False;
2225 catch ( ::com::sun::star::uno::Exception& )
2232 if ( !bSuccess )
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();
2253 else
2256 DBG_ERROR("Couldn't remove backup file!");
2260 else
2261 pImp->m_aBackupURL = ::rtl::OUString();
2264 //----------------------------------------------------------------
2265 void SfxMedium::GetMedium_Impl()
2267 if ( !pInStream )
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;
2289 else
2291 uno::Sequence < beans::PropertyValue > xProps;
2292 String aFileName;
2293 if ( aName.Len() )
2295 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aFileName ) )
2297 DBG_ERROR("Physical name not convertable!");
2300 else
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);
2320 if(m_bIsReadOnly)
2321 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
2323 // m_xInputStreamToLoadFrom = 0;
2325 else
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();
2341 else
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?!
2348 GetContent();
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 ) ) );
2369 if ( !GetError() )
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()
2404 return bRemote;
2407 //------------------------------------------------------------------
2409 void SfxMedium::SetUpdatePickList(sal_Bool bVal)
2411 if(!pImp)
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()
2438 GetInStream();
2441 void SfxMedium::DownLoad( const Link& aLink )
2443 SetDoneLink( aLink );
2444 GetInStream();
2445 if ( pInStream && !aLink.IsSet() )
2447 while( !pImp->bDownloadDone )
2448 Application::Yield();
2452 //------------------------------------------------------------------
2453 void SfxMedium::Init_Impl()
2454 /* [Beschreibung]
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
2457 vorhanden.
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!" );
2481 else
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
2491 if ( !aName.Len() )
2492 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aName );
2493 else {
2494 DBG_ASSERT( pSalvageItem, "Suspicious change of logical name!" );
2499 if ( pSalvageItem && pSalvageItem->GetValue().Len() )
2501 aLogicName = pSalvageItem->GetValue();
2502 DELETEZ( pURLObj );
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);
2509 if( pOutStreamItem
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 ) ) );
2528 SetIsRemote_Impl();
2531 //------------------------------------------------------------------
2532 SfxMedium::SfxMedium()
2533 : IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
2535 pFilter(0),
2536 pSet(0),
2537 pImp(new SfxMedium_Impl( this ))
2539 Init_Impl();
2541 //------------------------------------------------------------------
2543 SfxMedium::SfxMedium( const SfxMedium& rMedium, sal_Bool bTemporary )
2544 : SvRefBase(),
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();
2551 if ( !bTemporary )
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;
2559 Init_Impl();
2560 if( bTemporary )
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
2581 if ( pSet )
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() )
2586 return xHandler;
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*/ )
2612 pFilter = pFilterP;
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
2634 // storage
2635 //TODO/MBA: how to?! Do we need the flag?!
2637 const SvStream *pStream = aStorage->GetSvStream();
2638 if ( pStream && pStream == pInStream )
2640 CloseZipStorage_Impl();
2641 pInStream = NULL;
2642 pImp->xInputStream = Reference < XInputStream >();
2643 pImp->xLockBytes.Clear();
2644 if ( pSet )
2645 pSet->ClearItem( SID_INPUTSTREAM );
2646 aStorage->SetDeleteStream( TRUE );
2648 else if ( pStream && pStream == pOutStream )
2650 pOutStream = NULL;
2651 aStorage->SetDeleteStream( TRUE );
2652 } */
2654 CloseStorage();
2657 CloseStreams_Impl();
2659 UnlockFile();
2662 void SfxMedium::CloseAndRelease()
2664 if ( pImp->xStorage.is() )
2666 // don't close the streams if they belong to the
2667 // storage
2668 //TODO/MBA: how to?! Do we need the flag?!
2670 const SvStream *pStream = aStorage->GetSvStream();
2671 if ( pStream && pStream == pInStream )
2673 CloseZipStorage_Impl();
2674 pInStream = NULL;
2675 pImp->xInputStream = Reference < XInputStream >();
2676 pImp->xLockBytes.Clear();
2677 if ( pSet )
2678 pSet->ClearItem( SID_INPUTSTREAM );
2679 aStorage->SetDeleteStream( TRUE );
2681 else if ( pStream && pStream == pOutStream )
2683 pOutStream = NULL;
2684 aStorage->SetDeleteStream( TRUE );
2685 } */
2687 CloseStorage();
2690 CloseAndReleaseStreams_Impl();
2692 UnlockFile();
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();
2745 if ( pSet )
2746 pSet->ClearItem( SID_CONTENT );
2748 pImp->aContent = ::ucbhelper::Content();
2751 //------------------------------------------------------------------
2753 void SfxMedium::RefreshName_Impl()
2755 #if 0 //(dv)
2756 if ( pImp->aContent.get().is() )
2758 String aNameP = pImp->xAnchor->GetViewURL();
2759 pImp->aOrigURL = aNameP;
2760 aLogicName = aNameP;
2761 DELETEZ( pURLObj );
2762 if (aLogicName.Len())
2763 aLogicName = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
2764 SetIsRemote_Impl();
2766 #endif //(dv)
2769 void SfxMedium::SetIsRemote_Impl()
2771 INetURLObject aObj( GetName() );
2772 switch( aObj.GetProtocol() )
2774 case INET_PROT_FTP:
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:
2781 case INET_PROT_VIM:
2782 bRemote = TRUE; break;
2783 default:
2784 bRemote = ( GetName().CompareToAscii( "private:msgid", 13 ) == COMPARE_EQUAL );
2785 break;
2788 // Da Dateien, die Remote geschrieben werden zur Uebertragung auch
2789 // gelesen werden koennen muessen
2790 if( bRemote )
2791 nStorOpenMode |= STREAM_READ;
2796 void SfxMedium::SetName( const String& aNameP, sal_Bool bSetOrigURL )
2798 if( !pImp->aOrigURL.Len() )
2799 pImp->aOrigURL = aLogicName;
2800 if( bSetOrigURL )
2801 pImp->aOrigURL = aNameP;
2802 aLogicName = aNameP;
2803 DELETEZ( pURLObj );
2804 pImp->aContent = ::ucbhelper::Content();
2805 Init_Impl();
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();
2829 aName = rNameP;
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!" );
2852 return sal_True;
2855 //------------------------------------------------------------------
2857 void SfxMedium::ReOpen()
2859 BOOL bUseInteractionHandler = pImp->bUseInteractionHandler;
2860 pImp->bUseInteractionHandler = FALSE;
2861 GetMedium_Impl();
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;
2878 aName = String();
2881 GetMedium_Impl();
2883 if ( GetError() )
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();
2894 else
2896 pTmpFile->EnableKillingFile( sal_True );
2897 delete pTmpFile;
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
2911 pFilter(pFlt),
2912 pSet( pInSet ),
2913 pImp(new SfxMedium_Impl( this ))
2915 aLogicName = rName;
2916 nStorOpenMode = nOpenMode;
2917 bDirect = bDirectP;
2918 Init_Impl();
2922 SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
2923 : IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
2924 pFilter(0),
2925 pSet(0),
2926 pImp(new SfxMedium_Impl( this ))
2928 SfxAllItemSet *pParams = new SfxAllItemSet( SFX_APP()->GetPool() );
2929 pSet = pParams;
2930 TransformParameters( SID_OPENDOC, aArgs, *pParams );
2932 String aFilterName;
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 );
2940 if( pSalvageItem )
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 );
2959 else
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() )
2969 bReadOnly = TRUE;
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;
2975 bDirect = FALSE;
2976 Init_Impl();
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
2984 pSet(0),
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!" );
2991 Init_Impl();
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 ) );
2997 if ( p )
2998 GetItemSet()->Put( *p );
3001 //------------------------------------------------------------------
3003 SfxMedium::~SfxMedium()
3005 /* Attention
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
3013 ClearBackup_Impl();
3015 Close();
3017 delete pSet;
3019 if( pImp->bIsTemp && aName.Len() )
3021 String aTemp;
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!");
3033 pFilter = 0;
3035 delete pURLObj;
3036 delete pImp;
3039 //------------------------------------------------------------------
3040 void SfxMedium::SetItemSet(SfxItemSet *pNewSet)
3042 delete pSet;
3043 pSet = pNewSet;
3046 //----------------------------------------------------------------
3047 const INetURLObject& SfxMedium::GetURLObject() const
3049 if( !pURLObj )
3051 SfxMedium* pThis = const_cast < SfxMedium* > (this);
3052 pThis->pURLObj = new INetURLObject( aLogicName );
3053 if ( pThis->pURLObj->HasMark() )
3054 (*pThis->pURLObj) = INetURLObject( aLogicName ).GetURLNoMark();
3057 return *pURLObj;
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;
3080 GetMedium_Impl();
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, ';' );
3087 if( !eError )
3089 if( !pImp->aPreRedirectionURL.Len() )
3090 pImp->aPreRedirectionURL = aLogicName;
3091 SetName( pImp->xBinding->GetRedirectedURL() );
3093 pImp->aExpireTime = pImp->xBinding->GetExpireDateTime();
3095 return eError;
3097 return 0;
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 )
3129 if( pInStream )
3131 SvLockBytes* pBytes = pInStream->GetLockBytes();
3132 if( pBytes )
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
3160 if( !pSet )
3161 ((SfxMedium*)this)->pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
3162 return pSet;
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() )
3214 GetMedium_Impl();
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 );
3226 if ( xReader.is() )
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 );
3248 if ( xReader.is() )
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
3267 SvULongs aLongs;
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();
3272 sal_uInt16 n;
3273 for ( n=0; n<aLongs.Count(); n++ )
3274 if ( nVer<aLongs[n] )
3275 break;
3277 aLongs.Insert( nVer, n );
3280 sal_uInt16 nKey;
3281 for ( nKey=0; nKey<aLongs.Count(); nKey++ )
3282 if ( aLongs[nKey] > ( ULONG ) nKey+1 )
3283 break;
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;
3290 return nKey;
3293 return 0;
3296 sal_Bool SfxMedium::RemoveVersion_Impl( const ::rtl::OUString& rName )
3298 if ( !pImp->aVersions.getLength() )
3299 return sal_False;
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);
3309 return sal_True;
3313 return sal_False;
3316 sal_Bool SfxMedium::TransferVersionList_Impl( SfxMedium& rMedium )
3318 if ( rMedium.pImp->aVersions.getLength() )
3320 pImp->aVersions = rMedium.pImp->aVersions;
3321 return sal_True;
3324 return sal_False;
3327 sal_Bool SfxMedium::SaveVersionList_Impl( sal_Bool /*bUseXML*/ )
3329 if ( GetStorage().is() )
3331 if ( !pImp->aVersions.getLength() )
3332 return sal_True;
3334 uno::Reference < document::XDocumentRevisionListPersistence > xWriter( comphelper::getProcessServiceFactory()->createInstance(
3335 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3336 if ( xWriter.is() )
3340 xWriter->store( GetStorage(), pImp->aVersions );
3341 return sal_True;
3343 catch ( uno::Exception& )
3349 return sal_False;
3352 //----------------------------------------------------------------
3353 sal_Bool SfxMedium::IsReadOnly()
3355 sal_Bool bReadOnly = sal_False;
3357 // a) ReadOnly filter cant produce read/write contents!
3358 bReadOnly = (
3359 (pFilter ) &&
3360 ((pFilter->GetFilterFlags() & SFX_FILTER_OPENREADONLY) == SFX_FILTER_OPENREADONLY)
3363 // b) if filter allow read/write contents .. check open mode of the storage
3364 if (!bReadOnly)
3365 bReadOnly = !( GetOpenMode() & STREAM_WRITE );
3367 // c) the API can force the readonly state!
3368 if (!bReadOnly)
3370 SFX_ITEMSET_ARG( GetItemSet(), pItem, SfxBoolItem, SID_DOC_READONLY, sal_False);
3371 if (pItem)
3372 bReadOnly = pItem->GetValue();
3375 return bReadOnly;
3378 //----------------------------------------------------------------
3379 sal_Bool SfxMedium::SetWritableForUserOnly( const ::rtl::OUString& aURL )
3381 // UCB does not allow to allow write access only for the user,
3382 // use osl API
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 );
3404 return bResult;
3407 //----------------------------------------------------------------
3408 void SfxMedium::CreateTempFile( sal_Bool bReplace )
3410 if ( pImp->pTempFile )
3412 if ( !bReplace )
3413 return;
3415 DELETEZ( pImp->pTempFile );
3416 aName = String();
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 ) ) );
3426 return;
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,
3443 true,
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 ) ) );
3461 return;
3464 CloseOutStream();
3465 CloseInStream();
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
3471 GetOutStream();
3472 if ( pOutStream )
3474 char *pBuf = new char [8192];
3475 sal_uInt32 nErr = ERRCODE_NONE;
3477 pInStream->Seek(0);
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 );
3487 delete[] pBuf;
3488 CloseInStream();
3490 CloseOutStream_Impl();
3492 else
3493 CloseInStream();
3496 CloseStorage();
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();
3509 if ( !aName.Len() )
3511 SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3512 return;
3515 CloseOutStream_Impl();
3516 CloseStorage();
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;
3532 aAny >>= 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");
3541 if (pCharset != 0)
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" ) ),
3575 aArgs ),
3576 ::com::sun::star::uno::UNO_QUERY );
3578 if ( xSigner.is() )
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 );
3585 GetMedium_Impl();
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
3624 Commit();
3625 bChanges = TRUE;
3628 else
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
3643 Commit();
3644 bChanges = TRUE;
3648 catch ( uno::Exception& )
3650 OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
3653 CloseAndRelease();
3655 else
3659 if ( bScriptingContent )
3660 xSigner->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
3661 else
3662 xSigner->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
3664 catch( uno::Exception& )
3666 OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
3671 ResetError();
3674 return bChanges;
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();
3704 if ( !pBroker )
3705 throw uno::RuntimeException();
3707 uno::Reference< ::com::sun::star::ucb::XContentIdentifierFactory > xIdFac
3708 = pBroker->getContentIdentifierFactoryInterface();
3709 if ( !xIdFac.is() )
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" );
3733 return bResult;
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,
3761 true,
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,
3772 aFileName,
3773 NameClash::OVERWRITE ) )
3775 // Success
3776 aResult = aNewTempFileURL;
3779 catch( uno::Exception& )
3785 return aResult;
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();
3801 if ( bAllowAbort )
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& )
3817 return bResult;
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 );
3843 Close();
3844 SetPhysicalName_Impl( String() );
3845 SetName( aNewURL );
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 );
3855 GetMedium_Impl();
3856 LockOrigFileOnDemand( sal_False, sal_False );
3857 CreateTempFile( sal_True );
3858 GetMedium_Impl();
3860 if ( pImp->xStream.is() )
3864 xOptStorage->writeAndAttachToStream( pImp->xStream );
3865 pImp->xStorage = xStorage;
3866 aResult = aNewURL;
3868 catch( uno::Exception& )
3872 if ( !aResult.getLength() )
3874 Close();
3875 SetPhysicalName_Impl( String() );
3876 SetName( aOrigURL );
3877 if ( bWasReadonly )
3879 // set the readonly state back
3880 nStorOpenMode = SFX_STREAM_READONLY;
3881 GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY, sal_True));
3883 GetMedium_Impl();
3884 pImp->xStorage = xStorage;
3890 return aResult;
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 );
3908 Close();
3909 SetPhysicalName_Impl( String() );
3910 SetName( aURL );
3912 // open the temporary file based document
3913 GetMedium_Impl();
3914 LockOrigFileOnDemand( sal_False, sal_False );
3915 CreateTempFile( sal_True );
3916 GetMedium_Impl();
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;
3928 bResult = sal_True;
3930 catch( uno::Exception& )
3934 if ( !bResult )
3936 Close();
3937 SetPhysicalName_Impl( String() );
3938 SetName( aOrigURL );
3939 GetMedium_Impl();
3940 pImp->xStorage = xStorage;
3945 return bResult;