update dev300-m58
[ooovba.git] / sfx2 / source / doc / docfile.cxx
blobd4cc3f13c446ba965a0892826a7e1821980de0b9
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 <unotools/streamhelper.hxx>
88 #include <unotools/localedatawrapper.hxx>
89 #ifndef _MSGBOX_HXX //autogen
90 #include <vcl/msgbox.hxx>
91 #endif
92 #include <svtools/stritem.hxx>
93 #include <svtools/eitem.hxx>
94 #include <svtools/lckbitem.hxx>
95 #include <svtools/sfxecode.hxx>
96 #include <svtools/itemset.hxx>
97 #include <svtools/intitem.hxx>
98 #include <svtools/svparser.hxx> // SvKeyValue
99 #include <cppuhelper/weakref.hxx>
100 #include <cppuhelper/implbase1.hxx>
102 #define _SVSTDARR_ULONGS
103 #define _SVSTDARR_STRINGSDTOR
104 #include <svtools/svstdarr.hxx>
106 #include <unotools/streamwrap.hxx>
108 #include <rtl/logfile.hxx>
110 using namespace ::com::sun::star;
111 using namespace ::com::sun::star::uno;
112 using namespace ::com::sun::star::ucb;
113 using namespace ::com::sun::star::beans;
114 using namespace ::com::sun::star::io;
116 #include <comphelper/storagehelper.hxx>
117 #include <comphelper/mediadescriptor.hxx>
118 #include <comphelper/configurationhelper.hxx>
119 #include <tools/urlobj.hxx>
120 #include <tools/inetmime.hxx>
121 #include <unotools/ucblockbytes.hxx>
122 #include <svtools/pathoptions.hxx>
123 #include <svtools/asynclink.hxx>
124 #include <svtools/inettype.hxx>
125 #include <ucbhelper/contentbroker.hxx>
126 #include <ucbhelper/commandenvironment.hxx>
127 #include <unotools/localfilehelper.hxx>
128 #include <unotools/ucbstreamhelper.hxx>
129 #include <unotools/ucbhelper.hxx>
130 #include <unotools/progresshandlerwrap.hxx>
131 #include <ucbhelper/content.hxx>
132 #include <ucbhelper/interactionrequest.hxx>
133 #include <sot/stg.hxx>
134 #include <svtools/saveopt.hxx>
135 #include <svtools/documentlockfile.hxx>
137 #include "opostponedtruncationstream.hxx"
138 #include "helper.hxx"
139 #include <sfx2/request.hxx> // SFX_ITEMSET_SET
140 #include <sfx2/app.hxx> // GetFilterMatcher
141 #include <sfx2/frame.hxx> // LoadTargetFrame
142 #include "fltfnc.hxx" // SfxFilterMatcher
143 #include <sfx2/docfilt.hxx> // SfxFilter
144 #include <sfx2/objsh.hxx> // CheckOpenMode
145 #include <sfx2/docfac.hxx> // GetFilterContainer
146 #include "doc.hrc"
147 #include "openflag.hxx" // SFX_STREAM_READONLY etc.
148 #include "sfxresid.hxx"
149 #include <sfx2/appuno.hxx>
151 //#include "xmlversion.hxx"
153 #define MAX_REDIRECT 5
156 //==========================================================
157 namespace {
159 static const sal_Int8 LOCK_UI_NOLOCK = 0;
160 static const sal_Int8 LOCK_UI_SUCCEEDED = 1;
161 static const sal_Int8 LOCK_UI_TRY = 2;
163 //----------------------------------------------------------------
164 sal_Bool IsSystemFileLockingUsed()
166 // check whether system file locking has been used, the default value is false
167 sal_Bool bUseSystemLock = sal_False;
171 uno::Reference< uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig(
172 ::comphelper::getProcessServiceFactory(),
173 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
174 ::comphelper::ConfigurationHelper::E_STANDARD );
175 if ( !xCommonConfig.is() )
176 throw uno::RuntimeException();
178 ::comphelper::ConfigurationHelper::readRelativeKey(
179 xCommonConfig,
180 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
181 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentSystemFileLocking" ) ) ) >>= bUseSystemLock;
183 catch( const uno::Exception& )
187 return bUseSystemLock;
190 //----------------------------------------------------------------
191 sal_Bool IsOOoLockFileUsed()
193 // check whether system file locking has been used, the default value is false
194 sal_Bool bOOoLockFileUsed = sal_False;
198 uno::Reference< uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig(
199 ::comphelper::getProcessServiceFactory(),
200 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
201 ::comphelper::ConfigurationHelper::E_STANDARD );
202 if ( !xCommonConfig.is() )
203 throw uno::RuntimeException();
205 ::comphelper::ConfigurationHelper::readRelativeKey(
206 xCommonConfig,
207 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
208 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentOOoLockFile" ) ) ) >>= bOOoLockFileUsed;
210 catch( const uno::Exception& )
214 return bOOoLockFileUsed;
217 } // anonymous namespace
218 //==========================================================
221 //----------------------------------------------------------------
222 class SfxMediumHandler_Impl : public ::cppu::WeakImplHelper1< com::sun::star::task::XInteractionHandler >
224 com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > m_xInter;
226 public:
227 virtual void SAL_CALL handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& xRequest )
228 throw( com::sun::star::uno::RuntimeException );
230 SfxMediumHandler_Impl( com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > xInteraction )
231 : m_xInter( xInteraction )
234 ~SfxMediumHandler_Impl();
237 //----------------------------------------------------------------
238 SfxMediumHandler_Impl::~SfxMediumHandler_Impl()
242 //----------------------------------------------------------------
243 void SAL_CALL SfxMediumHandler_Impl::handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& xRequest )
244 throw( com::sun::star::uno::RuntimeException )
246 if( !m_xInter.is() )
247 return;
249 com::sun::star::uno::Any aRequest = xRequest->getRequest();
250 com::sun::star::ucb::InteractiveIOException aIoException;
251 com::sun::star::ucb::UnsupportedDataSinkException aSinkException;
252 if ( (aRequest >>= aIoException) && ( aIoException.Code == IOErrorCode_ACCESS_DENIED || aIoException.Code == IOErrorCode_LOCKING_VIOLATION ) )
253 return;
254 else
255 if ( aRequest >>= aSinkException )
256 return;
257 else
258 m_xInter->handle( xRequest );
261 //----------------------------------------------------------------
262 class SfxPoolCancelManager_Impl : public SfxCancelManager ,
263 public SfxCancellable ,
264 public SfxListener ,
265 public SvRefBase
267 SfxCancelManagerWeak wParent;
269 ~SfxPoolCancelManager_Impl();
270 public:
271 SfxPoolCancelManager_Impl( SfxCancelManager* pParent, const String& rName );
273 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
274 using SfxCancelManager::Cancel;
275 virtual void Cancel();
278 //----------------------------------------------------------------
279 SV_DECL_IMPL_REF( SfxPoolCancelManager_Impl )
282 //----------------------------------------------------------------
283 SfxPoolCancelManager_Impl::SfxPoolCancelManager_Impl( SfxCancelManager* pParent, const String& rName )
284 : SfxCancelManager( pParent ),
285 SfxCancellable( pParent ? pParent : this, rName ),
286 wParent( pParent )
288 if( pParent )
290 StartListening( *this );
291 SetManager( 0 );
295 //----------------------------------------------------------------
296 SfxPoolCancelManager_Impl::~SfxPoolCancelManager_Impl()
298 for( sal_uInt16 nPos = GetCancellableCount(); nPos--; )
300 // nicht an Parent uebernehmen!
301 SfxCancellable* pCbl = GetCancellable( nPos );
302 if ( pCbl )
303 pCbl->SetManager( 0 );
308 //----------------------------------------------------------------
309 void SfxPoolCancelManager_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& /*rHint*/ )
311 if( !GetCancellableCount() ) SetManager( 0 );
312 else if( !GetManager() )
314 if( !wParent.Is() ) wParent = SFX_APP()->GetCancelManager();
315 SetManager( wParent );
319 //----------------------------------------------------------------
320 void SfxPoolCancelManager_Impl::Cancel()
322 SfxPoolCancelManager_ImplRef xThis = this;
323 for( sal_uInt16 nPos = GetCancellableCount(); nPos--; )
325 SfxCancellable* pCbl = GetCancellable( nPos );
326 // Wenn wir nicht im Button stehen
327 if( pCbl && pCbl != this )
328 pCbl->Cancel();
329 if( GetCancellableCount() < nPos )
330 nPos = GetCancellableCount();
334 //----------------------------------------------------------------
335 class SfxMedium_Impl : public SvCompatWeakBase
337 public:
338 ::ucbhelper::Content aContent;
339 sal_Bool bUpdatePickList : 1;
340 sal_Bool bIsTemp : 1;
341 sal_Bool bForceSynchron : 1;
342 sal_Bool bDontCreateCancellable : 1;
343 sal_Bool bDownloadDone : 1;
344 sal_Bool bDontCallDoneLinkOnSharingError : 1;
345 sal_Bool bIsStorage: 1;
346 sal_Bool bUseInteractionHandler: 1;
347 sal_Bool bAllowDefaultIntHdl: 1;
348 sal_Bool bIsCharsetInitialized: 1;
349 sal_Bool bDisposeStorage: 1;
350 sal_Bool bStorageBasedOnInStream: 1;
351 sal_Bool m_bSalvageMode: 1;
352 sal_Bool m_bVersionsAlreadyLoaded: 1;
353 sal_Bool m_bLocked: 1;
354 sal_Bool m_bGotDateTime: 1;
356 uno::Reference < embed::XStorage > xStorage;
358 SfxPoolCancelManager_ImplRef xCancelManager;
359 SfxMedium* pAntiImpl;
361 long nFileVersion;
363 const SfxFilter* pOrigFilter;
364 String aOrigURL;
365 String aPreRedirectionURL;
366 String aReferer;
367 DateTime aExpireTime;
368 SfxFrameWeak wLoadTargetFrame;
369 SvKeyValueIteratorRef xAttributes;
371 svtools::AsynchronLink aDoneLink;
372 svtools::AsynchronLink aAvailableLink;
374 uno::Sequence < util::RevisionTag > aVersions;
376 ::utl::TempFile* pTempDir;
377 ::utl::TempFile* pTempFile;
379 uno::Reference < embed::XStorage > m_xReadStorage;
380 Reference < XInputStream > xInputStream;
381 Reference < XStream > xStream;
383 sal_uInt32 nLastStorageError;
384 ::rtl::OUString aCharset;
386 ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xInteraction;
388 sal_Bool m_bRemoveBackup;
389 ::rtl::OUString m_aBackupURL;
391 // the following member is changed and makes sence only during saving
392 // TODO/LATER: in future the signature state should be controlled by the medium not by the document
393 // in this case the member will hold this information
394 sal_uInt16 m_nSignatureState;
396 util::DateTime m_aDateTime;
398 uno::Reference< logging::XSimpleLogRing > m_xLogRing;
400 SfxPoolCancelManager_Impl* GetCancelManager();
402 SfxMedium_Impl( SfxMedium* pAntiImplP );
403 ~SfxMedium_Impl();
406 void SfxMedium::DataAvailable_Impl()
408 pImp->aAvailableLink.ClearPendingCall();
409 pImp->aAvailableLink.Call( NULL );
412 void SfxMedium::Cancel_Impl()
414 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
417 SfxPoolCancelManager_Impl* SfxMedium_Impl::GetCancelManager()
419 if( !xCancelManager.Is() )
421 if( !bDontCreateCancellable )
422 xCancelManager = new SfxPoolCancelManager_Impl(
423 wLoadTargetFrame ? wLoadTargetFrame->GetCancelManager() :
424 SFX_APP()->GetCancelManager(),
425 pAntiImpl->GetURLObject().GetURLNoPass() );
426 else
427 xCancelManager = new SfxPoolCancelManager_Impl(
428 0, pAntiImpl->GetURLObject().GetURLNoPass() );
430 return xCancelManager;
433 //------------------------------------------------------------------
434 SfxMedium_Impl::SfxMedium_Impl( SfxMedium* pAntiImplP )
435 : SvCompatWeakBase( pAntiImplP ),
436 bUpdatePickList(sal_True),
437 bIsTemp( sal_False ),
438 bForceSynchron( sal_False ),
439 bDontCreateCancellable( sal_False ),
440 bDownloadDone( sal_True ),
441 bDontCallDoneLinkOnSharingError( sal_False ),
442 bIsStorage( sal_False ),
443 bUseInteractionHandler( sal_True ),
444 bAllowDefaultIntHdl( sal_False ),
445 bIsCharsetInitialized( sal_False ),
446 bStorageBasedOnInStream( sal_False ),
447 m_bSalvageMode( sal_False ),
448 m_bVersionsAlreadyLoaded( sal_False ),
449 m_bLocked( sal_False ),
450 m_bGotDateTime( sal_False ),
451 pAntiImpl( pAntiImplP ),
452 nFileVersion( 0 ),
453 pOrigFilter( 0 ),
454 aExpireTime( Date() + 10, Time() ),
455 pTempDir( NULL ),
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;
474 if ( pTempDir )
475 delete pTempDir;
478 //================================================================
480 #define IMPL_CTOR(rootVal,URLVal) \
481 eError( SVSTREAM_OK ), \
483 bDirect( sal_False ), \
484 bRoot( rootVal ), \
485 bSetFilter( sal_False ), \
486 bTriedStorage( sal_False ), \
488 nStorOpenMode( SFX_STREAM_READWRITE ), \
489 pURLObj( URLVal ), \
490 pInStream(0), \
491 pOutStream( 0 )
493 //------------------------------------------------------------------
495 const SvGlobalName& SfxMedium::GetClassFilter()
497 GetMedium_Impl();
498 if( GetError() )
499 return aFilterClass;
500 if( !bSetFilter && GetStorage() )
501 SetClassFilter( GetStorage()->GetClassName() );
502 return aFilterClass;
505 //------------------------------------------------------------------
506 void SfxMedium::ResetError()
508 eError = SVSTREAM_OK;
509 if( pInStream )
510 pInStream->ResetError();
511 if( pOutStream )
512 pOutStream->ResetError();
515 //------------------------------------------------------------------
516 sal_uInt32 SfxMedium::GetLastStorageCreationState()
518 return pImp->nLastStorageError;
521 //------------------------------------------------------------------
522 void SfxMedium::AddLog( const ::rtl::OUString& aMessage )
524 if ( !pImp->m_xLogRing.is() )
528 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
529 if ( aContext.is() )
530 pImp->m_xLogRing.set( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), UNO_QUERY_THROW );
532 catch( uno::Exception& )
536 if ( pImp->m_xLogRing.is() )
537 pImp->m_xLogRing->logString( aMessage );
540 //------------------------------------------------------------------
541 void SfxMedium::SetError( sal_uInt32 nError, const ::rtl::OUString& aLogMessage )
543 eError = nError;
544 if ( eError != ERRCODE_NONE && aLogMessage.getLength() )
545 AddLog( aLogMessage );
548 //------------------------------------------------------------------
549 sal_uInt32 SfxMedium::GetErrorCode() const
551 sal_uInt32 lError=eError;
552 if(!lError && pInStream)
553 lError=pInStream->GetErrorCode();
554 if(!lError && pOutStream)
555 lError=pOutStream->GetErrorCode();
556 return lError;
559 //------------------------------------------------------------------
560 long SfxMedium::GetFileVersion() const
562 if ( !pImp->nFileVersion && pFilter )
563 return pFilter->GetVersion();
564 else
565 return pImp->nFileVersion;
568 //------------------------------------------------------------------
569 void SfxMedium::CheckFileDate( const util::DateTime& aInitDate )
571 GetInitFileDate( sal_True );
572 if ( pImp->m_aDateTime.Seconds != aInitDate.Seconds
573 || pImp->m_aDateTime.Minutes != aInitDate.Minutes
574 || pImp->m_aDateTime.Hours != aInitDate.Hours
575 || pImp->m_aDateTime.Day != aInitDate.Day
576 || pImp->m_aDateTime.Month != aInitDate.Month
577 || pImp->m_aDateTime.Year != aInitDate.Year )
579 uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
581 if ( xHandler.is() )
585 ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
586 document::ChangedByOthersRequest() ) );
587 uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
588 aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
589 aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
590 xInteractionRequestImpl->setContinuations( aContinuations );
592 xHandler->handle( xInteractionRequestImpl.get() );
594 ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
595 if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
597 SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
600 catch ( uno::Exception& )
606 //------------------------------------------------------------------
607 sal_Bool SfxMedium::DocNeedsFileDateCheck()
609 return ( !IsReadOnly() && SupportsActiveStreaming( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
612 //------------------------------------------------------------------
613 util::DateTime SfxMedium::GetInitFileDate( sal_Bool bIgnoreOldValue )
615 if ( ( bIgnoreOldValue || !pImp->m_bGotDateTime ) && GetContent().is() )
619 pImp->aContent.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "DateModified" )) ) >>= pImp->m_aDateTime;
620 pImp->m_bGotDateTime = sal_True;
622 catch ( ::com::sun::star::uno::Exception& )
627 return pImp->m_aDateTime;
630 //------------------------------------------------------------------
631 Reference < XContent > SfxMedium::GetContent() const
633 if ( !pImp->aContent.get().is() )
635 Reference < ::com::sun::star::ucb::XContent > xContent;
636 Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
638 SFX_ITEMSET_ARG( pSet, pItem, SfxUnoAnyItem, SID_CONTENT, sal_False);
639 if ( pItem )
640 pItem->GetValue() >>= xContent;
642 if ( xContent.is() )
646 pImp->aContent = ::ucbhelper::Content( xContent, xEnv );
648 catch ( Exception& )
652 else
654 // TODO: DBG_ERROR("SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
655 String aURL;
656 if ( aName.Len() )
657 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL );
658 else if ( aLogicName.Len() )
659 aURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
660 if ( aURL.Len() )
661 ::ucbhelper::Content::create( aURL, xEnv, pImp->aContent );
665 return pImp->aContent.get();
668 ::rtl::OUString SfxMedium::GetBaseURL( bool bForSaving )
670 ::rtl::OUString aBaseURL;
671 const SfxStringItem* pBaseURLItem = static_cast<const SfxStringItem*>( GetItemSet()->GetItem(SID_DOC_BASEURL) );
672 if ( pBaseURLItem )
673 aBaseURL = pBaseURLItem->GetValue();
674 else if ( GetContent().is() )
678 Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI" )) );
679 aAny >>= aBaseURL;
681 catch ( ::com::sun::star::uno::Exception& )
685 if ( !aBaseURL.getLength() )
686 aBaseURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
689 if ( bForSaving )
691 SvtSaveOptions aOpt;
692 sal_Bool bIsRemote = IsRemote();
693 if( (bIsRemote && !aOpt.IsSaveRelINet()) || (!bRemote && !aOpt.IsSaveRelFSys()) )
694 return ::rtl::OUString();
697 return aBaseURL;
700 //------------------------------------------------------------------
701 SvStream* SfxMedium::GetInStream()
703 if ( pInStream )
704 return pInStream;
706 if ( pImp->pTempFile || pImp->pTempDir )
708 pInStream = new SvFileStream( aName, nStorOpenMode );
710 eError = pInStream->GetError();
712 if( !eError && (nStorOpenMode & STREAM_WRITE)
713 && ! pInStream->IsWritable() )
715 eError = ERRCODE_IO_ACCESSDENIED;
716 delete pInStream;
717 pInStream = NULL;
719 else
720 return pInStream;
723 GetMedium_Impl();
725 if ( GetError() )
726 return NULL;
728 return pInStream;
731 //------------------------------------------------------------------
732 void SfxMedium::CloseInStream()
734 CloseInStream_Impl();
737 void SfxMedium::CloseInStream_Impl()
739 // if there is a storage based on the InStream, we have to
740 // close the storage, too, because otherwise the storage
741 // would use an invalid ( deleted ) stream.
742 if ( pInStream && pImp->xStorage.is() )
744 if ( pImp->bStorageBasedOnInStream )
745 CloseStorage();
748 if ( pInStream && !GetContent().is() )
750 CreateTempFile();
751 return;
754 DELETEZ( pInStream );
755 if ( pSet )
756 pSet->ClearItem( SID_INPUTSTREAM );
758 CloseReadStorage_Impl();
759 pImp->xInputStream = uno::Reference< io::XInputStream >();
761 if ( !pOutStream )
763 // output part of the stream is not used so the whole stream can be closed
764 // TODO/LATER: is it correct?
765 pImp->xStream = uno::Reference< io::XStream >();
766 if ( pSet )
767 pSet->ClearItem( SID_STREAM );
771 //------------------------------------------------------------------
772 SvStream* SfxMedium::GetOutStream()
774 if ( !pOutStream )
776 // Create a temp. file if there is none because we always
777 // need one.
778 if ( !pImp->pTempFile )
779 CreateTempFile();
781 if ( pImp->pTempFile )
783 pOutStream = new SvFileStream( aName, STREAM_STD_READWRITE );
784 CloseStorage();
788 return pOutStream;
791 //------------------------------------------------------------------
792 sal_Bool SfxMedium::CloseOutStream()
794 CloseOutStream_Impl();
795 return sal_True;
798 sal_Bool SfxMedium::CloseOutStream_Impl()
800 if ( pOutStream )
802 // if there is a storage based on the OutStream, we have to
803 // close the storage, too, because otherwise the storage
804 // would use an invalid ( deleted ) stream.
805 //TODO/MBA: how to deal with this?!
806 //maybe we need a new flag when the storage was created from the outstream
807 if ( pImp->xStorage.is() )
809 //const SvStream *pStorage = aStorage->GetSvStream();
810 //if ( pStorage == pOutStream )
811 CloseStorage();
814 delete pOutStream;
815 pOutStream = NULL;
818 if ( !pInStream )
820 // input part of the stream is not used so the whole stream can be closed
821 // TODO/LATER: is it correct?
822 pImp->xStream = uno::Reference< io::XStream >();
823 if ( pSet )
824 pSet->ClearItem( SID_STREAM );
827 return sal_True;
830 //------------------------------------------------------------------
831 const String& SfxMedium::GetPhysicalName( sal_Bool bForceCreateTempIfRemote ) const
833 if ( !aName.Len() && aLogicName.Len() )
835 if ( bForceCreateTempIfRemote || !SupportsActiveStreaming( aLogicName ) )
836 (( SfxMedium*)this)->CreateFileStream();
839 // return the name then
840 return aName;
843 //------------------------------------------------------------------
844 void SfxMedium::CreateFileStream()
846 ForceSynchronStream_Impl( TRUE );
847 GetInStream();
848 if( pInStream )
850 if ( !pImp->pTempFile )
851 CreateTempFile();
852 pImp->bIsTemp = sal_True;
853 CloseInStream_Impl();
857 //------------------------------------------------------------------
858 sal_Bool SfxMedium::Commit()
860 if( pImp->xStorage.is() )
861 StorageCommit_Impl();
862 else if( pOutStream )
863 pOutStream->Flush();
864 else if( pInStream )
865 pInStream->Flush();
867 if ( GetError() == SVSTREAM_OK )
869 // does something only in case there is a temporary file ( means aName points to different location than aLogicName )
870 Transfer_Impl();
873 sal_Bool bResult = ( GetError() == SVSTREAM_OK );
875 if ( bResult && DocNeedsFileDateCheck() )
876 GetInitFileDate( sal_True );
878 return bResult;
881 //------------------------------------------------------------------
882 sal_Bool SfxMedium::IsStorage()
884 if ( pImp->xStorage.is() )
885 return TRUE;
887 if ( bTriedStorage )
888 return pImp->bIsStorage;
890 if ( pImp->pTempFile )
892 String aURL;
893 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL ) )
895 DBG_ERROR("Physical name not convertable!");
897 pImp->bIsStorage = SotStorage::IsStorageFile( aURL ) && !SotStorage::IsOLEStorage( aURL);
898 if ( !pImp->bIsStorage )
899 bTriedStorage = TRUE;
901 else if ( GetInStream() )
903 pImp->bIsStorage = SotStorage::IsStorageFile( pInStream ) && !SotStorage::IsOLEStorage( pInStream );
904 if ( !pInStream->GetError() && !pImp->bIsStorage )
905 bTriedStorage = TRUE;
908 return pImp->bIsStorage;
911 //------------------------------------------------------------------
912 Link SfxMedium::GetDataAvailableLink() const
914 return pImp->aAvailableLink.GetLink();
917 //------------------------------------------------------------------
918 Link SfxMedium::GetDoneLink() const
920 return pImp->aDoneLink.GetLink();
923 //------------------------------------------------------------------
924 sal_Bool SfxMedium::IsPreview_Impl()
926 sal_Bool bPreview = sal_False;
927 SFX_ITEMSET_ARG( GetItemSet(), pPreview, SfxBoolItem, SID_PREVIEW, sal_False);
928 if ( pPreview )
929 bPreview = pPreview->GetValue();
930 else
932 SFX_ITEMSET_ARG( GetItemSet(), pFlags, SfxStringItem, SID_OPTIONS, sal_False);
933 if ( pFlags )
935 String aFileFlags = pFlags->GetValue();
936 aFileFlags.ToUpperAscii();
937 if ( STRING_NOTFOUND != aFileFlags.Search( 'B' ) )
938 bPreview = sal_True;
942 return bPreview;
945 //------------------------------------------------------------------
946 sal_Bool SfxMedium::TryStorage()
948 GetStorage();
950 if ( pImp->xStorage.is() )
951 return sal_True;
953 // this code will be removed when binary filter components are available!
954 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr( ::comphelper::getProcessServiceFactory() );
955 ::com::sun::star::uno::Reference< ::com::sun::star::util::XArchiver >
956 xPacker( xSMgr->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.util.Archiver" ) ), ::com::sun::star::uno::UNO_QUERY );
958 if( !xPacker.is() )
959 return sal_False;
961 // extract extra data
962 ::rtl::OUString aPath = GetURLObject().PathToFileName();
963 ::rtl::OUString aExtraData = xPacker->getExtraData( aPath );
964 const ::rtl::OUString aSig1( DEFINE_CONST_UNICODE( "private:" ) );
965 String aTmp( '?' );
966 aTmp += String::CreateFromAscii("simpress");//pFilter->GetFilterContainer()->GetName();
967 const ::rtl::OUString aSig2( aTmp );
968 sal_Int32 nIndex1 = aExtraData.indexOf( aSig1 );
969 sal_Int32 nIndex2 = aExtraData.indexOf( aSig2 );
971 if( nIndex1 != 0 || nIndex2 == -1 )
972 return sal_False;
974 nIndex1 += aSig1.getLength();
975 ::rtl::OUString aTempDoku = aExtraData.copy( nIndex1, nIndex2 - nIndex1 );
977 // create a temp dir to unpack to
978 pImp->pTempDir = new ::utl::TempFile( NULL, sal_True );
979 pImp->pTempDir->EnableKillingFile( sal_True );
981 // unpack all files to temp dir
982 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs;
983 com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
984 if (xInteractionHandler.is())
986 aArgs.realloc(1);
987 aArgs.getArray()[0].Name = DEFINE_CONST_UNICODE( "InteractionHandler" );
988 aArgs.getArray()[0].Value <<= xInteractionHandler ;
990 ::com::sun::star::uno::Sequence< ::rtl::OUString > files(0);
992 if( !xPacker->unpack( pImp->pTempDir->GetURL(), aPath, files, aArgs ) )
993 return sal_False;
995 String aNewName = pImp->pTempDir->GetURL();
996 aNewName += '/';
997 aNewName += String( aTempDoku );
998 CloseInStream_Impl();
999 String aTemp;
1000 ::utl::LocalFileHelper::ConvertURLToPhysicalName( aNewName, aTemp );
1001 SetPhysicalName_Impl( aTemp );
1002 GetStorage();
1004 return pImp->xStorage.is();
1007 //------------------------------------------------------------------
1008 sal_Bool SfxMedium::SupportsActiveStreaming( const rtl::OUString &rName ) const
1010 if ( ::utl::LocalFileHelper::IsLocalFile( rName ) )
1011 return sal_True;
1013 ::ucbhelper::Content aTmpContent;
1014 Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
1015 if ( ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aTmpContent ) )
1017 Any aAny = aTmpContent.getPropertyValue(
1018 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "SupportsActiveStreaming" )) );
1020 sal_Bool bSupportsStreaming = sal_False;
1021 return ( ( aAny >>= bSupportsStreaming ) && bSupportsStreaming );
1024 return sal_False;
1027 //------------------------------------------------------------------
1028 sal_Bool SfxMedium::BasedOnOriginalFile_Impl()
1030 return ( !pImp->pTempFile && !( aLogicName.Len() && pImp->m_bSalvageMode )
1031 && GetURLObject().GetMainURL( INetURLObject::NO_DECODE ).getLength()
1032 && SupportsActiveStreaming( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
1033 && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
1036 //------------------------------------------------------------------
1037 void SfxMedium::StorageBackup_Impl()
1039 ::ucbhelper::Content aOriginalContent;
1040 Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
1041 if ( BasedOnOriginalFile_Impl() && !pImp->m_aBackupURL.getLength()
1042 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aOriginalContent ) )
1044 DoInternalBackup_Impl( aOriginalContent );
1045 if( !pImp->m_aBackupURL.getLength() )
1046 SetError( ERRCODE_SFX_CANTCREATEBACKUP, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1050 //------------------------------------------------------------------
1051 ::rtl::OUString SfxMedium::GetBackup_Impl()
1053 if ( !pImp->m_aBackupURL.getLength() )
1054 StorageBackup_Impl();
1056 return pImp->m_aBackupURL;
1059 //------------------------------------------------------------------
1060 ::rtl::OUString SfxMedium::GetOutputStorageURL_Impl()
1062 String aStorageName;
1064 if ( aName.Len() )
1066 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aStorageName ) )
1068 DBG_ERROR("Physical name not convertable!");
1071 else
1073 aStorageName = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
1076 return aStorageName;
1079 //------------------------------------------------------------------
1080 uno::Reference < embed::XStorage > SfxMedium::GetOutputStorage()
1082 if ( GetError() )
1083 return uno::Reference< embed::XStorage >();
1085 // if the medium was constructed with a Storage: use this one, not a temp. storage
1086 // if a temporary storage already exists: use it
1087 if ( pImp->xStorage.is() && ( !aLogicName.Len() || pImp->pTempFile ) )
1088 return pImp->xStorage;
1090 // if necessary close stream that was used for reading
1091 if ( pInStream && !pInStream->IsWritable() )
1092 CloseInStream();
1094 DBG_ASSERT( !pOutStream, "OutStream in a readonly Medium?!" );
1096 // medium based on OutputStream: must work with TempFile
1097 if( aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL
1098 || !::utl::LocalFileHelper::IsLocalFile( aLogicName ) )
1099 CreateTempFileNoCopy();
1100 // if Medium already contains a stream - TODO/LATER: store stream/outputstream in ImplData, not in Medium
1101 else if ( GetItemSet()->GetItemState( SID_STREAM ) < SFX_ITEM_SET )
1103 // check whether the backup should be created
1104 StorageBackup_Impl();
1106 if ( GetError() )
1107 return uno::Reference< embed::XStorage >();
1109 ::rtl::OUString aOutputURL = GetOutputStorageURL_Impl();
1111 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
1112 SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
1113 sal_Bool bRename = pRename ? pRename->GetValue() : FALSE;
1114 sal_Bool bOverWrite = pOverWrite ? pOverWrite->GetValue() : !bRename;
1116 // the target file must be truncated before a storage based on it is created
1119 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
1120 uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xSimpleFileAccess(
1121 xFactory->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.ucb.SimpleFileAccess") ),
1122 uno::UNO_QUERY_THROW );
1124 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
1125 ::ucbhelper::Content aContent = ::ucbhelper::Content( aOutputURL, xDummyEnv );
1127 uno::Reference< io::XStream > xStream;
1128 sal_Bool bDeleteOnFailure = sal_False;
1132 xStream = aContent.openWriteableStreamNoLock();
1134 if ( !bOverWrite )
1136 // the stream should not exist, it should not be possible to open it
1137 if ( xStream->getOutputStream().is() )
1138 xStream->getOutputStream()->closeOutput();
1139 if ( xStream->getInputStream().is() )
1140 xStream->getInputStream()->closeInput();
1142 xStream = uno::Reference< io::XStream >();
1143 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1146 catch ( ucb::InteractiveIOException const & e )
1148 if ( e.Code == ucb::IOErrorCode_NOT_EXISTING )
1150 // Create file...
1151 SvMemoryStream aStream(0,0);
1152 uno::Reference< io::XInputStream > xInput( new ::utl::OInputStreamWrapper( aStream ) );
1153 ucb::InsertCommandArgument aInsertArg;
1154 aInsertArg.Data = xInput;
1155 aInsertArg.ReplaceExisting = sal_False;
1156 aContent.executeCommand( rtl::OUString::createFromAscii( "insert" ), uno::makeAny( aInsertArg ) );
1158 // Try to open one more time
1159 xStream = aContent.openWriteableStreamNoLock();
1160 bDeleteOnFailure = sal_True;
1162 else
1163 throw;
1166 if ( xStream.is() )
1168 if ( BasedOnOriginalFile_Impl() )
1170 // the storage will be based on original file, the wrapper should be used
1171 xStream = new OPostponedTruncationFileStream( aOutputURL, xFactory, xSimpleFileAccess, xStream, bDeleteOnFailure );
1173 else
1175 // the storage will be based on the temporary file, the stream can be truncated directly
1176 uno::Reference< io::XOutputStream > xOutStream = xStream->getOutputStream();
1177 uno::Reference< io::XTruncate > xTruncate( xOutStream, uno::UNO_QUERY );
1178 if ( !xTruncate.is() )
1179 throw uno::RuntimeException();
1181 xTruncate->truncate();
1182 xOutStream->flush();
1185 pImp->xStream = xStream;
1186 GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM, makeAny( xStream ) ) );
1189 catch( uno::Exception& )
1191 // TODO/LATER: try to use the temporary file in case the target content can not be opened, it might happen in case of some FS, the copy functionality might work in this case
1192 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1196 return GetStorage();
1199 //------------------------------------------------------------------
1200 void SfxMedium::SetPasswordToStorage_Impl()
1202 // in case media-descriptor contains password it should be used on opening
1203 if ( pImp->xStorage.is() && pSet )
1205 ::rtl::OUString aPasswd;
1206 if ( GetPasswd_Impl( pSet, aPasswd ) )
1210 ::comphelper::OStorageHelper::SetCommonStoragePassword( pImp->xStorage, aPasswd );
1212 catch( uno::Exception& )
1214 OSL_ENSURE( sal_False, "It must be possible to set a common password for the storage" );
1215 // TODO/LATER: set the error code in case of problem
1216 // SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1222 //------------------------------------------------------------------
1223 sal_Int8 SfxMedium::ShowLockedDocumentDialog( const uno::Sequence< ::rtl::OUString >& aData, sal_Bool bIsLoading, sal_Bool bOwnLock )
1225 sal_Int8 nResult = LOCK_UI_NOLOCK;
1227 // show the interaction regarding the document opening
1228 uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
1230 if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler.is() && ( bIsLoading || bOwnLock ) )
1232 ::rtl::OUString aDocumentURL = GetURLObject().GetLastName();
1233 ::rtl::OUString aInfo;
1234 ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl;
1236 if ( bOwnLock )
1238 if ( aData.getLength() > LOCKFILE_EDITTIME_ID )
1239 aInfo = aData[LOCKFILE_EDITTIME_ID];
1241 xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
1242 document::OwnLockOnDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo, !bIsLoading ) ) );
1244 else
1246 if ( aData.getLength() > LOCKFILE_EDITTIME_ID )
1248 if ( aData[LOCKFILE_OOOUSERNAME_ID].getLength() )
1249 aInfo = aData[LOCKFILE_OOOUSERNAME_ID];
1250 else
1251 aInfo = aData[LOCKFILE_SYSUSERNAME_ID];
1253 if ( aInfo.getLength() && aData[LOCKFILE_EDITTIME_ID].getLength() )
1255 aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " ( " ) );
1256 aInfo += aData[LOCKFILE_EDITTIME_ID];
1257 aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " )" ) );
1261 if ( bIsLoading )
1263 xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
1264 document::LockedDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
1266 else
1268 xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
1269 document::LockedOnSavingRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
1274 uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
1275 aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
1276 aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
1277 aContinuations[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl.get() );
1278 xInteractionRequestImpl->setContinuations( aContinuations );
1280 xHandler->handle( xInteractionRequestImpl.get() );
1282 ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
1283 if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
1285 SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1287 else if ( uno::Reference< task::XInteractionDisapprove >( xSelected.get(), uno::UNO_QUERY ).is() )
1289 // own lock on loading, user has selected to ignore the lock
1290 // own lock on saving, user has selected to ignore the lock
1291 // alien lock on loading, user has selected to edit a copy of document
1292 // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
1293 if ( bIsLoading && !bOwnLock )
1295 // means that a copy of the document should be opened
1296 GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE, sal_True ) );
1298 else if ( bOwnLock )
1299 nResult = LOCK_UI_SUCCEEDED;
1301 else // if ( XSelected == aContinuations[1] )
1303 // own lock on loading, user has selected to open readonly
1304 // own lock on saving, user has selected to open readonly
1305 // alien lock on loading, user has selected to retry saving
1306 // TODO/LATER: alien lock on saving, user has selected to retry saving
1308 if ( bIsLoading )
1309 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1310 else
1311 nResult = LOCK_UI_TRY;
1314 else
1316 if ( bIsLoading )
1318 // if no interaction handler is provided the default answer is open readonly
1319 // that usually happens in case the document is loaded per API
1320 // so the document must be opened readonly for backward compatibility
1321 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1323 else
1324 SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1328 return nResult;
1331 //------------------------------------------------------------------
1332 sal_Bool SfxMedium::LockOrigFileOnDemand( sal_Bool bLoading, sal_Bool bNoUI )
1334 // returns true if the document can be opened for editing ( even if it should be a copy )
1335 // otherwise the document should be opened readonly
1336 // if user cancel the loading the ERROR_ABORT is set
1338 sal_Bool bResult = pImp->m_bLocked;
1340 if ( !bResult )
1342 // no read-write access is necessary on loading if the document is explicitly opened as copy
1343 SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem, SfxBoolItem, SID_TEMPLATE, sal_False);
1344 bResult = ( bLoading && pTemplateItem && pTemplateItem->GetValue() );
1347 if ( !bResult && !IsReadOnly() )
1349 // check whether the file is readonly in fs
1350 // do it only for loading, some contents still might have problems with this property, let them not affect the saving
1351 sal_Bool bContentReadonly = sal_False;
1352 if ( bLoading )
1356 // MediaDescriptor does this check also, the duplication should be avoided in future
1357 pImp->aContent.getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) ) >>= bContentReadonly;
1359 catch( uno::Exception )
1363 if ( !bContentReadonly )
1365 if ( ::utl::LocalFileHelper::IsLocalFile( aLogicName ) )
1367 // the special file locking should be used only for file URLs
1369 // in case of storing the document should request the output before locking
1370 if ( bLoading )
1372 // let the stream be opened to check the system file locking
1373 GetMedium_Impl();
1376 sal_Int8 bUIStatus = LOCK_UI_NOLOCK;
1378 // check whether system file locking has been used, the default value is false
1379 sal_Bool bUseSystemLock = IsSystemFileLockingUsed();
1381 // TODO/LATER: This implementation does not allow to detect the system lock on saving here, actually this is no big problem
1382 // if system lock is used the writeable stream should be available
1383 sal_Bool bHandleSysLocked = ( bLoading && bUseSystemLock && !pImp->xStream.is() && !pOutStream );
1389 ::svt::DocumentLockFile aLockFile( aLogicName );
1390 if ( !bHandleSysLocked )
1394 bResult = aLockFile.CreateOwnLockFile();
1396 catch ( ucb::InteractiveIOException& e )
1398 // exception means that the lock file can not be successfuly accessed
1399 // in this case it should be ignored if system file locking is anyway active
1400 if ( bUseSystemLock || !IsOOoLockFileUsed() )
1402 bResult = sal_True;
1403 // take the ownership over the lock file
1404 aLockFile.OverwriteOwnLockFile();
1406 else if ( e.Code == IOErrorCode_INVALID_PARAMETER )
1408 // system file locking is not active, ask user whether he wants to open the document without any locking
1409 uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
1411 if ( xHandler.is() )
1413 ::rtl::Reference< ::ucbhelper::InteractionRequest > xIgnoreRequestImpl
1414 = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
1416 uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 2 );
1417 aContinuations[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl.get() );
1418 aContinuations[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl.get() );
1419 xIgnoreRequestImpl->setContinuations( aContinuations );
1421 xHandler->handle( xIgnoreRequestImpl.get() );
1423 ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xIgnoreRequestImpl->getSelection();
1424 bResult = ( uno::Reference< task::XInteractionApprove >( xSelected.get(), uno::UNO_QUERY ).is() );
1428 catch ( uno::Exception& )
1430 // exception means that the lock file can not be successfuly accessed
1431 // in this case it should be ignored if system file locking is anyway active
1432 if ( bUseSystemLock || !IsOOoLockFileUsed() )
1434 bResult = sal_True;
1435 // take the ownership over the lock file
1436 aLockFile.OverwriteOwnLockFile();
1440 // in case OOo locking is turned off the lock file is still written if possible
1441 // but it is ignored while deciding whether the document should be opened for editing or not
1442 if ( !bResult && !IsOOoLockFileUsed() )
1444 bResult = sal_True;
1445 // take the ownership over the lock file
1446 aLockFile.OverwriteOwnLockFile();
1451 if ( !bResult )
1453 uno::Sequence< ::rtl::OUString > aData;
1456 // impossibility to get data is no real problem
1457 aData = aLockFile.GetLockData();
1459 catch( uno::Exception ) {}
1461 sal_Bool bOwnLock = sal_False;
1463 if ( !bHandleSysLocked )
1465 uno::Sequence< ::rtl::OUString > aOwnData = aLockFile.GenerateOwnEntry();
1466 bOwnLock = ( aData.getLength() > LOCKFILE_USERURL_ID
1467 && aOwnData.getLength() > LOCKFILE_USERURL_ID
1468 && aOwnData[LOCKFILE_SYSUSERNAME_ID].equals( aData[LOCKFILE_SYSUSERNAME_ID] ) );
1470 if ( bOwnLock
1471 && aOwnData[LOCKFILE_LOCALHOST_ID].equals( aData[LOCKFILE_LOCALHOST_ID] )
1472 && aOwnData[LOCKFILE_USERURL_ID].equals( aData[LOCKFILE_USERURL_ID] ) )
1474 // this is own lock from the same installation, it could remain because of crash
1475 bResult = sal_True;
1479 if ( !bResult && !bNoUI )
1481 bUIStatus = ShowLockedDocumentDialog( aData, bLoading, bOwnLock );
1482 if ( bUIStatus == LOCK_UI_SUCCEEDED )
1484 // take the ownership over the lock file
1485 bResult = aLockFile.OverwriteOwnLockFile();
1489 bHandleSysLocked = sal_False;
1492 catch( uno::Exception& )
1495 } while( !bResult && bUIStatus == LOCK_UI_TRY );
1497 pImp->m_bLocked = bResult;
1499 else
1501 // this is no file URL, check whether the file is readonly
1502 bResult = !bContentReadonly;
1507 if ( !bResult && GetError() == ERRCODE_NONE )
1509 // the error should be set in case it is storing process
1510 // or the document has been opened for editing explicitly
1512 SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, FALSE );
1513 if ( !bLoading || (pReadOnlyItem && !pReadOnlyItem->GetValue()) )
1514 SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1515 else
1516 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1519 // when the file is locked, get the current file date
1520 if ( bResult && DocNeedsFileDateCheck() )
1521 GetInitFileDate( sal_True );
1523 return bResult;
1526 //------------------------------------------------------------------
1527 uno::Reference < embed::XStorage > SfxMedium::GetStorage()
1529 if ( pImp->xStorage.is() || bTriedStorage )
1530 return pImp->xStorage;
1532 uno::Sequence< uno::Any > aArgs( 2 );
1534 String aStorageName;
1535 if ( pImp->pTempFile || pImp->pTempDir )
1537 // open storage from the temporary file
1538 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aStorageName ) )
1540 DBG_ERROR("Physical name not convertable!");
1543 CloseOutStream();
1544 // create the set of the streams based on the temporary file
1545 GetMedium_Impl();
1547 OSL_ENSURE( pImp->xStream.is(), "It must be possible to create read write stream access!" );
1548 if ( pImp->xStream.is() )
1550 aArgs[0] <<= pImp->xStream;
1551 pImp->bStorageBasedOnInStream = sal_True;
1553 else
1555 CloseStreams_Impl();
1556 aArgs[0] <<= ::rtl::OUString( aName );
1557 pImp->bStorageBasedOnInStream = sal_False;
1560 aArgs[1] <<= ( nStorOpenMode&STREAM_WRITE ? embed::ElementModes::READWRITE : embed::ElementModes::READ );
1564 pImp->xStorage = uno::Reference< embed::XStorage >(
1565 ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs ),
1566 uno::UNO_QUERY );
1568 catch( uno::Exception& )
1570 //TODO/LATER: error handling; Error and LastStorageError
1573 else
1575 // open the storage from original location
1577 GetMedium_Impl();
1578 if ( GetError() )
1579 return pImp->xStorage;
1583 if ( IsReadOnly() && SupportsActiveStreaming( aLogicName ) )
1585 //TODO/LATER: performance problem if not controlled by special Mode in SfxMedium
1586 //(should be done only for permanently open storages)
1587 // create a copy, the following method will close all existing streams
1588 CreateTempFile();
1590 // create the set of the streams based on the temporary file
1591 GetMedium_Impl();
1593 OSL_ENSURE( pImp->xStream.is(), "It must be possible to create read write stream access!" );
1594 if ( pImp->xStream.is() )
1596 aArgs[0] <<= pImp->xStream;
1597 pImp->bStorageBasedOnInStream = sal_True;
1599 else
1601 CloseStreams_Impl();
1602 aArgs[0] <<= ::rtl::OUString( aName );
1603 pImp->bStorageBasedOnInStream = sal_False;
1606 aArgs[1] <<= embed::ElementModes::READWRITE;
1609 else
1611 // there is no explicit request to open the document readonly
1613 // create a storage on the stream
1614 if ( pImp->xStream.is() )
1616 aArgs[0] <<= pImp->xStream;
1617 aArgs[1] <<= ( ( nStorOpenMode & STREAM_WRITE ) ?
1618 embed::ElementModes::READWRITE : embed::ElementModes::READ );
1620 pImp->bStorageBasedOnInStream = sal_True;
1622 else
1624 // no readwrite stream, but it can be a case of http protocol
1625 sal_Bool bReadOnly = sal_False;
1627 if ( aLogicName.CompareToAscii( "private:stream", 14 ) != COMPARE_EQUAL
1628 && GetContent().is() )
1630 // unfortunately the content can not always have the interaction handler
1631 // so in some cases it has to be set for some time
1632 Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
1633 Reference < ::com::sun::star::ucb::XCommandEnvironment > xOldEnv;
1634 Reference < ::com::sun::star::task::XInteractionHandler > xInteractionHandler = ((SfxMedium*)this)->GetInteractionHandler();
1635 if ( xInteractionHandler.is() )
1636 xEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler,
1637 Reference< ::com::sun::star::ucb::XProgressHandler >() );
1639 if ( xEnv.is() )
1641 xOldEnv = pImp->aContent.getCommandEnvironment();
1642 pImp->aContent.setCommandEnvironment( xEnv );
1647 Any aAny = pImp->aContent.getPropertyValue(
1648 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsReadOnly" )) );
1650 if ( ( aAny >>= bReadOnly ) && bReadOnly )
1652 GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY, sal_True));
1653 SetOpenMode( SFX_STREAM_READONLY, sal_False, sal_True );
1656 catch( uno::Exception& )
1659 if ( xEnv.is() )
1660 pImp->aContent.setCommandEnvironment( xOldEnv );
1663 // if the document is opened as readonly the copy should be done according to selected approach
1664 // if the document is opened for editing the copy should be done to use it as a temporary location for changes before the final transfer
1665 // the following method will close all existing streams
1666 CreateTempFile();
1668 // create the set of the streams based on the temporary file
1669 GetMedium_Impl();
1671 OSL_ENSURE( pImp->xStream.is(), "It must be possible to create read write stream access!" );
1672 if ( pImp->xStream.is() )
1674 aArgs[0] <<= pImp->xStream;
1675 pImp->bStorageBasedOnInStream = sal_True;
1677 else
1679 CloseStreams_Impl();
1680 aArgs[0] <<= ::rtl::OUString( aName );
1681 pImp->bStorageBasedOnInStream = sal_False;
1684 if ( bReadOnly )
1685 aArgs[1] <<= embed::ElementModes::READ;
1686 else
1687 aArgs[1] <<= embed::ElementModes::READWRITE;
1691 SFX_ITEMSET_ARG( GetItemSet(), pRepairItem, SfxBoolItem, SID_REPAIRPACKAGE, sal_False);
1692 if ( pRepairItem && pRepairItem->GetValue() )
1694 // the storage should be created for repairing mode
1695 CreateTempFile();
1696 Reference< ::com::sun::star::ucb::XProgressHandler > xProgressHandler;
1697 Reference< ::com::sun::star::task::XStatusIndicator > xStatusIndicator;
1699 SFX_ITEMSET_ARG( GetItemSet(), pxProgressItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, sal_False );
1700 if( pxProgressItem && ( pxProgressItem->GetValue() >>= xStatusIndicator ) )
1701 xProgressHandler = Reference< ::com::sun::star::ucb::XProgressHandler >(
1702 new utl::ProgressHandlerWrap( xStatusIndicator ) );
1704 uno::Sequence< beans::PropertyValue > aAddProps( 2 );
1705 aAddProps[0].Name = ::rtl::OUString::createFromAscii( "RepairPackage" );
1706 aAddProps[0].Value <<= (sal_Bool)sal_True;
1707 aAddProps[1].Name = ::rtl::OUString::createFromAscii( "StatusIndicator" );
1708 aAddProps[1].Value <<= xProgressHandler;
1710 aArgs.realloc( 3 );
1711 aArgs[0] <<= ::rtl::OUString( aName );
1712 aArgs[1] <<= embed::ElementModes::READWRITE;
1713 aArgs[2] <<= aAddProps;
1715 pImp->bStorageBasedOnInStream = sal_False;
1718 pImp->xStorage = uno::Reference< embed::XStorage >(
1719 ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs ),
1720 uno::UNO_QUERY );
1722 if ( !pImp->xStorage.is() )
1723 throw uno::RuntimeException();
1725 if ( pRepairItem && pRepairItem->GetValue() )
1727 // in repairing mode the mediatype required by filter should be used
1728 ::rtl::OUString aMediaType;
1729 ::rtl::OUString aMediaTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
1730 uno::Reference < beans::XPropertySet > xPropSet( pImp->xStorage, uno::UNO_QUERY_THROW );
1731 xPropSet->getPropertyValue( aMediaTypePropName ) >>= aMediaType;
1732 if ( !aMediaType.getLength() && pFilter )
1733 xPropSet->setPropertyValue( aMediaTypePropName,
1734 uno::makeAny( ::rtl::OUString( pFilter->GetMimeType() ) ) );
1737 catch ( uno::Exception& )
1739 //TODO/MBA: error handling; Error and LastStorageError
1740 pImp->bStorageBasedOnInStream = sal_False;
1745 if( ( pImp->nLastStorageError = GetError() ) != SVSTREAM_OK )
1747 pImp->xStorage = 0;
1748 if ( pInStream )
1749 pInStream->Seek(0);
1750 return NULL;
1753 bTriedStorage = sal_True;
1755 //TODO/MBA: error handling; Error and LastStorageError
1756 //if ( aStorage->GetError() == SVSTREAM_OK )
1757 if ( pImp->xStorage.is() )
1759 SetPasswordToStorage_Impl();
1760 GetVersionList();
1763 SFX_ITEMSET_ARG( pSet, pVersion, SfxInt16Item, SID_VERSION, sal_False);
1765 BOOL bResetStorage = FALSE;
1766 if ( pVersion && pVersion->GetValue() )
1768 // Alle verf"ugbaren Versionen einlesen
1769 if ( pImp->aVersions.getLength() )
1771 // Die zum Kommentar passende Version suchen
1772 // Die Versionen sind von 1 an durchnumeriert, mit negativen
1773 // Versionsnummern werden die Versionen von der aktuellen aus
1774 // r"uckw"arts gez"ahlt
1775 short nVersion = pVersion ? pVersion->GetValue() : 0;
1776 if ( nVersion<0 )
1777 nVersion = ( (short) pImp->aVersions.getLength() ) + nVersion;
1778 else if ( nVersion )
1779 nVersion--;
1781 util::RevisionTag& rTag = pImp->aVersions[nVersion];
1783 // SubStorage f"ur alle Versionen "offnen
1784 uno::Reference < embed::XStorage > xSub = pImp->xStorage->openStorageElement( DEFINE_CONST_UNICODE( "Versions" ),
1785 embed::ElementModes::READ );
1787 DBG_ASSERT( xSub.is(), "Versionsliste, aber keine Versionen!" );
1789 // Dort ist die Version als gepackter Stream gespeichert
1790 uno::Reference < io::XStream > xStr = xSub->openStreamElement( rTag.Identifier, embed::ElementModes::READ );
1791 SvStream* pStream = utl::UcbStreamHelper::CreateStream( xStr );
1792 if ( pStream && pStream->GetError() == SVSTREAM_OK )
1794 // Stream ins TempDir auspacken
1795 ::utl::TempFile aTempFile;
1796 String aTmpName = aTempFile.GetURL();
1797 SvFileStream aTmpStream( aTmpName, SFX_STREAM_READWRITE );
1799 *pStream >> aTmpStream;
1800 aTmpStream.Close();
1802 // Datei als Storage "offnen
1803 nStorOpenMode = SFX_STREAM_READONLY;
1804 pImp->xStorage = comphelper::OStorageHelper::GetStorageFromURL( aTmpName, embed::ElementModes::READ );
1805 pImp->bStorageBasedOnInStream = sal_False;
1806 String aTemp;
1807 ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName, aTemp );
1808 SetPhysicalName_Impl( aTemp );
1810 pImp->bIsTemp = sal_True;
1811 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1812 // TODO/MBA
1813 pImp->aVersions.realloc(0);
1815 else
1816 bResetStorage = TRUE;
1819 else
1820 bResetStorage = TRUE;
1823 //TODO/MBA: error handling; Error and LastStorageError
1824 if ( pImp->xStorage.is() )
1825 { /*
1826 if( ( pImp->nLastStorageError = aStorage->GetError() ) != SVSTREAM_OK )
1827 bResetStorage = TRUE;
1828 else if ( GetFilter() )
1829 aStorage->SetVersion( GetFilter()->GetVersion() );*/
1832 if ( bResetStorage )
1834 pImp->xStorage = 0;
1835 if ( pInStream )
1836 pInStream->Seek( 0L );
1839 pImp->bIsStorage = pImp->xStorage.is();
1840 return pImp->xStorage;
1843 //------------------------------------------------------------------
1844 uno::Reference< embed::XStorage > SfxMedium::GetLastCommitReadStorage_Impl()
1846 if ( !GetError() && !pImp->m_xReadStorage.is() )
1848 GetMedium_Impl();
1852 if ( pImp->xInputStream.is() )
1854 uno::Sequence< uno::Any > aArgs( 2 );
1855 aArgs[0] <<= pImp->xInputStream;
1856 aArgs[1] <<= embed::ElementModes::READ;
1857 pImp->m_xReadStorage = uno::Reference< embed::XStorage >(
1858 ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs ),
1859 uno::UNO_QUERY );
1861 else if ( GetStorage().is() )
1863 uno::Reference< embed::XStorage > xTempStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
1864 GetStorage()->copyLastCommitTo( xTempStor );
1865 pImp->m_xReadStorage = xTempStor;
1868 catch( uno::Exception& )
1870 OSL_ENSURE( sal_False, "No possibility to get readonly version of storage from medium!\n" );
1873 if ( GetError() ) // do not remove warnings
1874 ResetError();
1877 return pImp->m_xReadStorage;
1880 //------------------------------------------------------------------
1881 void SfxMedium::CloseReadStorage_Impl()
1883 if ( pImp->m_xReadStorage.is() )
1885 try {
1886 pImp->m_xReadStorage->dispose();
1887 } catch( uno::Exception& )
1890 pImp->m_xReadStorage = uno::Reference< embed::XStorage >();
1894 //------------------------------------------------------------------
1895 void SfxMedium::CloseStorage()
1897 if ( pImp->xStorage.is() )
1899 uno::Reference < lang::XComponent > xComp( pImp->xStorage, uno::UNO_QUERY );
1900 // in the salvage mode the medium does not own the storage
1901 if ( pImp->bDisposeStorage && !pImp->m_bSalvageMode )
1903 try {
1904 xComp->dispose();
1905 } catch( uno::Exception& )
1907 OSL_ENSURE( sal_False, "Medium's storage is already disposed!\n" );
1911 pImp->xStorage = 0;
1912 pImp->bStorageBasedOnInStream = sal_False;
1915 bTriedStorage = sal_False;
1916 pImp->bIsStorage = sal_False;
1919 void SfxMedium::CanDisposeStorage_Impl( sal_Bool bDisposeStorage )
1921 pImp->bDisposeStorage = bDisposeStorage;
1924 sal_Bool SfxMedium::WillDisposeStorageOnClose_Impl()
1926 return pImp->bDisposeStorage;
1929 //------------------------------------------------------------------
1930 void SfxMedium::SetOpenMode( StreamMode nStorOpen,
1931 sal_Bool bDirectP,
1932 sal_Bool bDontClose )
1934 if ( nStorOpenMode != nStorOpen )
1936 nStorOpenMode = nStorOpen;
1938 if( !bDontClose )
1940 if ( pImp->xStorage.is() )
1941 CloseStorage();
1943 CloseStreams_Impl();
1947 bDirect = bDirectP;
1948 bSetFilter = sal_False;
1951 //------------------------------------------------------------------
1952 sal_Bool SfxMedium::UseBackupToRestore_Impl( ::ucbhelper::Content& aOriginalContent,
1953 const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
1957 ::ucbhelper::Content aTransactCont( pImp->m_aBackupURL, xComEnv );
1959 Reference< XInputStream > aOrigInput = aTransactCont.openStream();
1960 aOriginalContent.writeStream( aOrigInput, sal_True );
1961 return sal_True;
1963 catch( Exception& )
1965 // in case of failure here the backup file should not be removed
1966 // TODO/LATER: a message should be used to let user know about the backup
1967 pImp->m_bRemoveBackup = sal_False;
1968 // TODO/LATER: needs a specific error code
1969 eError = ERRCODE_IO_GENERAL;
1972 return sal_False;
1975 //------------------------------------------------------------------
1976 sal_Bool SfxMedium::StorageCommit_Impl()
1978 sal_Bool bResult = sal_False;
1979 Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
1980 ::ucbhelper::Content aOriginalContent;
1982 if ( pImp->xStorage.is() )
1984 if ( !GetError() )
1986 uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
1987 if ( xTrans.is() )
1991 xTrans->commit();
1992 CloseReadStorage_Impl();
1993 bResult = sal_True;
1995 catch ( embed::UseBackupException& aBackupExc )
1997 if ( !pImp->pTempFile )
1999 OSL_ENSURE( pImp->m_aBackupURL.getLength(), "No backup on storage commit!\n" );
2000 if ( pImp->m_aBackupURL.getLength()
2001 && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
2002 xDummyEnv,
2003 aOriginalContent ) )
2005 // use backup to restore the file
2006 // the storage has already disconnected from original location
2007 CloseAndReleaseStreams_Impl();
2008 if ( !UseBackupToRestore_Impl( aOriginalContent, xDummyEnv ) )
2010 // connect the medium to the temporary file of the storage
2011 pImp->aContent = ::ucbhelper::Content();
2012 aName = aBackupExc.TemporaryFileURL;
2013 OSL_ENSURE( aName.Len(), "The exception _must_ contain the temporary URL!\n" );
2017 if ( !GetError() )
2018 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
2021 catch ( uno::Exception& )
2023 //TODO/LATER: improve error handling
2024 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
2030 return bResult;
2033 //------------------------------------------------------------------
2034 sal_Bool SfxMedium::TransactedTransferForFS_Impl( const INetURLObject& aSource,
2035 const INetURLObject& aDest,
2036 const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
2038 sal_Bool bResult = sal_False;
2039 Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
2040 Reference< XOutputStream > aDestStream;
2041 ::ucbhelper::Content aOriginalContent;
2043 // actualy it should work even for contents different from file content
2044 // DBG_ASSERT( ::utl::LocalFileHelper::IsLocalFile( aDest.GetMainURL( INetURLObject::NO_DECODE ) ),
2045 // "SfxMedium::TransactedTransferForFS() should be used only for local contents!" );
2048 aOriginalContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
2050 catch ( ::com::sun::star::ucb::CommandAbortedException& )
2052 eError = ERRCODE_ABORT;
2054 catch ( ::com::sun::star::ucb::CommandFailedException& )
2056 eError = ERRCODE_ABORT;
2058 catch (const ::com::sun::star::ucb::ContentCreationException& ex)
2060 eError = ERRCODE_IO_GENERAL;
2061 if (
2062 (ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER ) ||
2063 (ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
2066 eError = ERRCODE_IO_NOTEXISTSPATH;
2069 catch (const ::com::sun::star::uno::Exception&)
2071 eError = ERRCODE_IO_GENERAL;
2074 if( !eError || (eError & ERRCODE_WARNING_MASK) )
2076 if ( pImp->xStorage.is() )
2077 CloseStorage();
2079 CloseStreams_Impl();
2081 ::ucbhelper::Content aTempCont;
2082 if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aTempCont ) )
2084 sal_Bool bTransactStarted = sal_False;
2085 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
2086 SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
2087 sal_Bool bRename = pRename ? pRename->GetValue() : FALSE;
2088 sal_Bool bOverWrite = pOverWrite ? pOverWrite->GetValue() : !bRename;
2092 if( bOverWrite && ::utl::UCBContentHelper::IsDocument( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) )
2094 if( ! pImp->m_aBackupURL.getLength() )
2095 DoInternalBackup_Impl( aOriginalContent );
2097 if( pImp->m_aBackupURL.getLength() )
2099 Reference< XInputStream > aTempInput = aTempCont.openStream();
2100 bTransactStarted = sal_True;
2101 aOriginalContent.setPropertyValue( ::rtl::OUString::createFromAscii( "Size" ),
2102 uno::makeAny( (sal_Int64)0 ) );
2103 aOriginalContent.writeStream( aTempInput, bOverWrite );
2104 bResult = sal_True;
2106 else
2108 eError = ERRCODE_SFX_CANTCREATEBACKUP;
2111 else
2113 Reference< XInputStream > aTempInput = aTempCont.openStream();
2114 aOriginalContent.writeStream( aTempInput, bOverWrite );
2115 bResult = sal_True;
2118 catch ( ::com::sun::star::ucb::CommandAbortedException& )
2120 eError = ERRCODE_ABORT;
2122 catch ( ::com::sun::star::ucb::CommandFailedException& )
2124 eError = ERRCODE_ABORT;
2126 catch ( ::com::sun::star::ucb::InteractiveIOException& r )
2128 if ( r.Code == IOErrorCode_ACCESS_DENIED )
2129 eError = ERRCODE_IO_ACCESSDENIED;
2130 else if ( r.Code == IOErrorCode_NOT_EXISTING )
2131 eError = ERRCODE_IO_NOTEXISTS;
2132 else if ( r.Code == IOErrorCode_CANT_READ )
2133 eError = ERRCODE_IO_CANTREAD;
2134 else
2135 eError = ERRCODE_IO_GENERAL;
2137 catch ( ::com::sun::star::uno::Exception& )
2139 eError = ERRCODE_IO_GENERAL;
2142 if ( bResult )
2144 if ( pImp->pTempFile )
2146 pImp->pTempFile->EnableKillingFile( sal_True );
2147 delete pImp->pTempFile;
2148 pImp->pTempFile = NULL;
2151 else if ( bTransactStarted )
2153 UseBackupToRestore_Impl( aOriginalContent, xDummyEnv );
2156 else
2157 eError = ERRCODE_IO_CANTREAD;
2160 return bResult;
2163 //------------------------------------------------------------------
2164 sal_Bool SfxMedium::TryDirectTransfer( const ::rtl::OUString& aURL, SfxItemSet& aTargetSet )
2166 if ( GetError() )
2167 return sal_False;
2169 // if the document had no password it should be stored without password
2170 // if the document had password it should be stored with the same password
2171 // otherwise the stream copying can not be done
2172 SFX_ITEMSET_ARG( &aTargetSet, pNewPassItem, SfxStringItem, SID_PASSWORD, sal_False );
2173 SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem, SfxStringItem, SID_PASSWORD, sal_False );
2174 if ( ( !pNewPassItem && !pOldPassItem )
2175 || ( pNewPassItem && pOldPassItem && pNewPassItem->GetValue().Equals( pOldPassItem->GetValue() ) ) )
2177 // the filter must be the same
2178 SFX_ITEMSET_ARG( &aTargetSet, pNewFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
2179 SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
2180 if ( pNewFilterItem && pOldFilterItem && pNewFilterItem->GetValue().Equals( pOldFilterItem->GetValue() ) )
2182 // get the input stream and copy it
2183 // in case of success return true
2184 uno::Reference< io::XInputStream > xInStream = GetInputStream();
2186 ResetError();
2187 if ( xInStream.is() )
2191 uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
2192 sal_Int64 nPos = 0;
2193 if ( xSeek.is() )
2195 nPos = xSeek->getPosition();
2196 xSeek->seek( 0 );
2199 uno::Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
2200 ::ucbhelper::Content aTargetContent( aURL, xEnv );
2202 InsertCommandArgument aInsertArg;
2203 aInsertArg.Data = xInStream;
2204 SFX_ITEMSET_ARG( &aTargetSet, pRename, SfxBoolItem, SID_RENAME, sal_False );
2205 SFX_ITEMSET_ARG( &aTargetSet, pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
2206 if ( (pOverWrite && !pOverWrite->GetValue()) // argument says: never overwrite
2207 || (pRename && pRename->GetValue()) ) // argument says: rename file
2208 aInsertArg.ReplaceExisting = sal_False;
2209 else
2210 aInsertArg.ReplaceExisting = sal_True; // default is overwrite existing files
2212 Any aCmdArg;
2213 aCmdArg <<= aInsertArg;
2214 aTargetContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
2215 aCmdArg );
2217 if ( xSeek.is() )
2218 xSeek->seek( nPos );
2220 return sal_True;
2222 catch( uno::Exception& )
2228 return sal_False;
2231 //------------------------------------------------------------------
2232 void SfxMedium::Transfer_Impl()
2234 // The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
2235 String aNameURL;
2236 if ( pImp->pTempFile )
2237 aNameURL = pImp->pTempFile->GetURL();
2238 else if ( aLogicName.Len() && pImp->m_bSalvageMode )
2240 // makes sence only in case logic name is set
2241 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aNameURL ) )
2242 OSL_ENSURE( sal_False, "The medium name is not convertable!\n" );
2245 if ( aNameURL.Len() && ( !eError || (eError & ERRCODE_WARNING_MASK) ) )
2247 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::Transfer_Impl, copying to target" );
2249 Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
2250 Reference< XOutputStream > rOutStream;
2252 // in case an output stream is provided from outside and the URL is correct
2253 // commit to the stream
2254 if( aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL )
2256 // TODO/LATER: support storing to SID_STREAM
2257 SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
2258 if( pOutStreamItem && ( pOutStreamItem->GetValue() >>= rOutStream ) )
2260 if ( pImp->xStorage.is() )
2261 CloseStorage();
2263 CloseStreams_Impl();
2265 INetURLObject aSource( aNameURL );
2266 ::ucbhelper::Content aTempCont;
2267 if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aTempCont ) )
2271 sal_Int32 nRead;
2272 sal_Int32 nBufferSize = 32767;
2273 Sequence < sal_Int8 > aSequence ( nBufferSize );
2274 Reference< XInputStream > aTempInput = aTempCont.openStream();
2278 nRead = aTempInput->readBytes ( aSequence, nBufferSize );
2279 if ( nRead < nBufferSize )
2281 Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
2282 rOutStream->writeBytes ( aTempBuf );
2284 else
2285 rOutStream->writeBytes ( aSequence );
2287 while ( nRead == nBufferSize );
2289 // remove temporary file
2290 if ( pImp->pTempFile )
2292 pImp->pTempFile->EnableKillingFile( sal_True );
2293 delete pImp->pTempFile;
2294 pImp->pTempFile = NULL;
2297 catch( Exception& )
2301 else
2303 DBG_ERROR( "Illegal Output stream parameter!\n" );
2304 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
2307 // free the reference
2308 if ( pSet )
2309 pSet->ClearItem( SID_OUTPUTSTREAM );
2311 return;
2314 GetContent();
2315 if ( !pImp->aContent.get().is() )
2317 eError = ERRCODE_IO_NOTEXISTS;
2318 return;
2321 SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize, SfxInt32Item, SID_SEGMENTSIZE, sal_False);
2322 if ( pSegmentSize )
2324 // this file must be stored into a disk spanned package
2327 uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetStorageFromURL( GetName(),
2328 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
2330 // set segment size property; package will automatically be divided in pieces fitting
2331 // into this size
2332 ::com::sun::star::uno::Any aAny;
2333 aAny <<= pSegmentSize->GetValue();
2335 uno::Reference < beans::XPropertySet > xSet( pImp->xStorage, uno::UNO_QUERY );
2336 xSet->setPropertyValue( String::CreateFromAscii("SegmentSize"), aAny );
2338 // copy the temporary storage into the disk spanned package
2339 GetStorage()->copyToStorage( xStor );
2340 uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
2341 if ( xTrans.is() )
2342 xTrans->commit();
2345 catch ( uno::Exception& )
2347 //TODO/MBA: error handling
2348 //if ( !GetError() )
2349 // SetError( xStor->GetError(, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )) );
2351 return;
2354 if ( pFilter && SOFFICE_FILEFORMAT_60 <= pFilter->GetVersion() )
2356 //TODO/LATER: how?!
2358 SFX_ITEMSET_ARG( GetItemSet(), pItem, SfxBoolItem, SID_UNPACK, sal_False);
2359 if ( pItem && pItem->GetValue() )
2361 // this file must be stored without packing into a JAR file
2362 // check for an existing unpacked storage
2363 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( GetName(), STREAM_STD_READ );
2364 if ( !pStream->GetError() )
2366 String aURL = UCBStorage::GetLinkedFile( *pStream );
2367 if ( aURL.Len() )
2368 // remove a possibly existing old folder
2369 ::utl::UCBContentHelper::Kill( aURL );
2371 DELETEZ( pStream );
2374 // create a new folder based storage
2375 SvStorageRef xStor = new SvStorage( TRUE, GetName(), STREAM_STD_READWRITE, STORAGE_CREATE_UNPACKED );
2377 // copy package into unpacked storage
2378 if ( xStor->GetError() == ERRCODE_NONE && GetStorage()->copyToStorage( xStor ) )
2380 // commit changes, writing will happen now
2381 xStor->Commit();
2383 // take new unpacked storage as own storage
2384 if ( pImp->xStorage.is() )
2385 CloseStorage();
2387 CloseStreams_Impl();
2389 DELETEZ( pImp->pTempFile );
2390 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aName );
2391 SetStorage_Impl( xStor );
2393 else if ( !GetError() )
2394 SetError( xStor->GetError(, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )) );
2395 return;
2399 INetURLObject aDest( GetURLObject() );
2401 // source is the temp file written so far
2402 INetURLObject aSource( aNameURL );
2404 // a special case, an interaction handler should be used for
2405 // authentication in case it is available
2406 Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
2407 Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
2408 if (xInteractionHandler.is())
2409 xComEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler,
2410 Reference< ::com::sun::star::ucb::XProgressHandler >() );
2412 if ( SupportsActiveStreaming( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) || !aDest.removeSegment() )
2414 TransactedTransferForFS_Impl( aSource, aDest, xComEnv );
2416 else
2418 // create content for the parent folder and call transfer on that content with the source content
2419 // and the destination file name as parameters
2420 ::ucbhelper::Content aSourceContent;
2421 ::ucbhelper::Content aTransferContent;
2423 String aFileName = GetLongName();
2424 if ( !aFileName.Len() )
2425 aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2429 aTransferContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
2431 catch (const ::com::sun::star::ucb::ContentCreationException& ex)
2433 eError = ERRCODE_IO_GENERAL;
2434 if (
2435 (ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER ) ||
2436 (ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
2439 eError = ERRCODE_IO_NOTEXISTSPATH;
2442 catch (const ::com::sun::star::uno::Exception&)
2444 eError = ERRCODE_IO_GENERAL;
2447 if ( !eError || (eError & ERRCODE_WARNING_MASK) )
2449 // free resources, otherwise the transfer may fail
2450 if ( pImp->xStorage.is() )
2451 CloseStorage();
2453 CloseStreams_Impl();
2455 ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent );
2457 // check for external parameters that may customize the handling of NameClash situations
2458 SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
2459 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
2460 sal_Int32 nNameClash;
2461 if ( pOverWrite && !pOverWrite->GetValue() )
2462 // argument says: never overwrite
2463 nNameClash = NameClash::ERROR;
2464 else if ( pRename && pRename->GetValue() )
2465 // argument says: rename file
2466 nNameClash = NameClash::RENAME;
2467 else
2468 // default is overwrite existing files
2469 nNameClash = NameClash::OVERWRITE;
2473 if (!aTransferContent.transferContent( aSourceContent, ::ucbhelper::InsertOperation_COPY, aFileName, nNameClash ))
2474 eError = ERRCODE_IO_GENERAL;
2476 catch ( ::com::sun::star::ucb::CommandAbortedException& )
2478 eError = ERRCODE_ABORT;
2480 catch ( ::com::sun::star::ucb::CommandFailedException& )
2482 eError = ERRCODE_ABORT;
2484 catch ( ::com::sun::star::ucb::InteractiveIOException& r )
2486 if ( r.Code == IOErrorCode_ACCESS_DENIED )
2487 eError = ERRCODE_IO_ACCESSDENIED;
2488 else if ( r.Code == IOErrorCode_NOT_EXISTING )
2489 eError = ERRCODE_IO_NOTEXISTS;
2490 else if ( r.Code == IOErrorCode_CANT_READ )
2491 eError = ERRCODE_IO_CANTREAD;
2492 else
2493 eError = ERRCODE_IO_GENERAL;
2495 catch ( ::com::sun::star::uno::Exception& )
2497 eError = ERRCODE_IO_GENERAL;
2500 // do not switch from temporary file in case of nonfile protocol
2504 if ( ( !eError || (eError & ERRCODE_WARNING_MASK) ) && !pImp->pTempFile )
2506 // without a TempFile the physical and logical name should be the same after successful transfer
2507 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
2508 aName );
2509 pImp->m_bSalvageMode = sal_False;
2514 //------------------------------------------------------------------
2515 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent,
2516 const String& aPrefix,
2517 const String& aExtension,
2518 const String& aDestDir )
2520 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoInternalBackup_Impl( with destdir )" );
2522 if ( pImp->m_aBackupURL.getLength() )
2523 return; // the backup was done already
2525 ::rtl::OUString aBackupName;
2526 ::rtl::OUString aBackupURL;
2528 // a living aTransactTemp kills WebDAV with SAL_ENABLE_FILE_LOCKING=1,
2529 // because then it attempts to have 2 file handles pointing to the same
2530 // file name...
2531 ::utl::TempFile aTransactTemp( aPrefix, &aExtension, &aDestDir );
2532 aTransactTemp.EnableKillingFile( sal_True );
2534 INetURLObject aBackObj( aTransactTemp.GetURL() );
2536 aBackupName = aBackObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2537 aBackupURL = aBackObj.GetMainURL( INetURLObject::NO_DECODE );
2540 Reference < ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
2541 ::ucbhelper::Content aBackupCont;
2542 if( ::ucbhelper::Content::create( aDestDir, xDummyEnv, aBackupCont ) )
2546 if( aBackupCont.transferContent( aOriginalContent,
2547 ::ucbhelper::InsertOperation_COPY,
2548 aBackupName,
2549 NameClash::OVERWRITE ) )
2551 pImp->m_aBackupURL = aBackupURL;
2552 pImp->m_bRemoveBackup = sal_True;
2555 catch( Exception& )
2560 //------------------------------------------------------------------
2561 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent )
2563 if ( pImp->m_aBackupURL.getLength() )
2564 return; // the backup was done already
2566 ::rtl::OUString aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT,
2567 true,
2568 INetURLObject::NO_DECODE );
2570 sal_Int32 nPrefixLen = aFileName.lastIndexOf( '.' );
2571 String aPrefix = ( nPrefixLen == -1 ) ? aFileName : aFileName.copy( 0, nPrefixLen );
2572 String aExtension = ( nPrefixLen == -1 ) ? String() : String(aFileName.copy( nPrefixLen ));
2573 String aBakDir = SvtPathOptions().GetBackupPath();
2575 DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aBakDir );
2577 if ( !pImp->m_aBackupURL.getLength() )
2579 // the copiing to the backup catalog failed ( for example because
2580 // of using an encrypted partition as target catalog )
2581 // since the user did not specify to make backup explicitly
2582 // office should try to make backup in another place,
2583 // target catalog does not look bad for this case ( and looks
2584 // to be the only way for encrypted partitions )
2586 INetURLObject aDest = GetURLObject();
2587 if ( aDest.removeSegment() )
2588 DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aDest.GetMainURL( INetURLObject::NO_DECODE ) );
2593 //------------------------------------------------------------------
2594 void SfxMedium::DoBackup_Impl()
2596 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoBackup_Impl" );
2598 // source file name is the logical name of this medium
2599 INetURLObject aSource( GetURLObject() );
2601 // there is nothing to backup in case source file does not exist
2602 if ( !::utl::UCBContentHelper::IsDocument( aSource.GetMainURL( INetURLObject::NO_DECODE ) ) )
2603 return;
2605 sal_Bool bSuccess = sal_False;
2607 // get path for backups
2608 String aBakDir = SvtPathOptions().GetBackupPath();
2609 if( aBakDir.Len() )
2611 // create content for the parent folder ( = backup folder )
2612 ::ucbhelper::Content aContent;
2613 Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
2614 if( ::ucbhelper::Content::create( aBakDir, xEnv, aContent ) )
2616 // save as ".bak" file
2617 INetURLObject aDest( aBakDir );
2618 aDest.insertName( aSource.getName() );
2619 aDest.setExtension( DEFINE_CONST_UNICODE( "bak" ) );
2620 String aFileName = aDest.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2622 // create a content for the source file
2623 ::ucbhelper::Content aSourceContent;
2624 if ( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent ) )
2628 // do the transfer ( copy source file to backup dir )
2629 bSuccess = aContent.transferContent( aSourceContent,
2630 ::ucbhelper::InsertOperation_COPY,
2631 aFileName,
2632 NameClash::OVERWRITE );
2633 if( bSuccess )
2635 pImp->m_aBackupURL = aDest.GetMainURL( INetURLObject::NO_DECODE );
2636 pImp->m_bRemoveBackup = sal_False;
2639 catch ( ::com::sun::star::uno::Exception& )
2646 if ( !bSuccess )
2648 eError = ERRCODE_SFX_CANTCREATEBACKUP;
2652 //------------------------------------------------------------------
2653 void SfxMedium::ClearBackup_Impl()
2655 if( pImp->m_bRemoveBackup )
2657 // currently a document is always stored in a new medium,
2658 // thus if a backup can not be removed the backup URL should not be cleaned
2659 if ( pImp->m_aBackupURL.getLength() )
2661 if ( ::utl::UCBContentHelper::Kill( pImp->m_aBackupURL ) )
2662 // || !::utl::UCBContentHelper::IsDocument( pImp->m_aBackupURL ) );
2664 pImp->m_bRemoveBackup = sal_False;
2665 pImp->m_aBackupURL = ::rtl::OUString();
2667 else
2670 DBG_ERROR("Couldn't remove backup file!");
2674 else
2675 pImp->m_aBackupURL = ::rtl::OUString();
2678 //----------------------------------------------------------------
2679 void SfxMedium::GetMedium_Impl()
2681 if ( !pInStream )
2683 pImp->bDownloadDone = sal_False;
2684 Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
2686 //TODO/MBA: need support for SID_STREAM
2687 SFX_ITEMSET_ARG( pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, sal_False);
2688 SFX_ITEMSET_ARG( pSet, pInStreamItem, SfxUnoAnyItem, SID_INPUTSTREAM, sal_False);
2689 if ( pWriteStreamItem )
2691 pWriteStreamItem->GetValue() >>= pImp->xStream;
2693 if ( pInStreamItem )
2694 pInStreamItem->GetValue() >>= pImp->xInputStream;
2696 if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2697 pImp->xInputStream = pImp->xStream->getInputStream();
2699 else if ( pInStreamItem )
2701 pInStreamItem->GetValue() >>= pImp->xInputStream;
2703 else
2705 uno::Sequence < beans::PropertyValue > xProps;
2706 String aFileName;
2707 if ( aName.Len() )
2709 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aFileName ) )
2711 DBG_ERROR("Physical name not convertable!");
2714 else
2715 aFileName = GetName();
2717 // in case the temporary file exists the streams should be initialized from it,
2718 // but the original MediaDescriptor should not be changed
2719 sal_Bool bFromTempFile = ( pImp->pTempFile || pImp->pTempDir );
2721 if ( !bFromTempFile )
2723 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, aFileName ) );
2724 if( !(nStorOpenMode & STREAM_WRITE ) )
2725 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, TRUE ) );
2726 if (xInteractionHandler.is())
2727 GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER, makeAny(xInteractionHandler) ) );
2730 if ( m_xInputStreamToLoadFrom.is() )
2732 pImp->xInputStream = m_xInputStreamToLoadFrom;
2733 pImp->xInputStream->skipBytes(0);
2734 if(m_bIsReadOnly)
2735 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
2737 // m_xInputStreamToLoadFrom = 0;
2739 else
2741 TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
2742 comphelper::MediaDescriptor aMedium( xProps );
2744 if ( bFromTempFile )
2746 aMedium[comphelper::MediaDescriptor::PROP_URL()] <<= ::rtl::OUString( aFileName );
2747 aMedium.erase( comphelper::MediaDescriptor::PROP_READONLY() );
2748 aMedium.addInputStream();
2750 else if ( SupportsActiveStreaming( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
2752 // use the special locking approach only for file URLs
2753 aMedium.addInputStreamOwnLock();
2755 else
2756 aMedium.addInputStream();
2758 // the ReadOnly property set in aMedium is ignored
2759 // the check is done in LockOrigFileOnDemand() for file and non-file URLs
2761 //TODO/MBA: what happens if property is not there?!
2762 GetContent();
2763 aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp->xStream;
2764 aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp->xInputStream;
2765 if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2766 pImp->xInputStream = pImp->xStream->getInputStream();
2769 if ( !bFromTempFile )
2771 //TODO/MBA: need support for SID_STREAM
2772 if ( pImp->xStream.is() )
2773 GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM, makeAny( pImp->xStream ) ) );
2775 GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM, makeAny( pImp->xInputStream ) ) );
2779 //TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
2780 if ( !GetError() && !pImp->xStream.is() && !pImp->xInputStream.is() )
2781 SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
2783 if ( !GetError() )
2785 if ( pImp->xStream.is() )
2786 pInStream = utl::UcbStreamHelper::CreateStream( pImp->xStream );
2787 else if ( pImp->xInputStream.is() )
2788 pInStream = utl::UcbStreamHelper::CreateStream( pImp->xInputStream );
2791 pImp->bDownloadDone = sal_True;
2792 pImp->aDoneLink.ClearPendingCall();
2793 pImp->aDoneLink.Call( (void*) GetError() );
2797 //------------------------------------------------------------------
2798 SfxPoolCancelManager_Impl* SfxMedium::GetCancelManager_Impl() const
2800 return pImp->GetCancelManager();
2803 //------------------------------------------------------------------
2804 void SfxMedium::SetCancelManager_Impl( SfxPoolCancelManager_Impl* pMgr )
2806 pImp->xCancelManager = pMgr;
2809 //----------------------------------------------------------------
2810 void SfxMedium::CancelTransfers()
2812 if( pImp->xCancelManager.Is() )
2813 pImp->xCancelManager->Cancel();
2816 //----------------------------------------------------------------
2818 String SfxMedium::GetStatusString( const SvProgressArg* pArg )
2820 String aString;
2821 StringList_Impl aSL( SfxResId( RID_DLSTATUS2 ), (USHORT)pArg->eStatus );
2822 USHORT nTotal = 0;
2824 if ( pArg->eStatus == SVBINDSTATUS_ENDDOWNLOADDATA && nTotal <= 1 )
2825 return aString;
2827 if( aSL )
2829 INetURLObject aObj( pArg->rStatus );
2830 aString = aSL.GetString();
2831 aString.SearchAndReplaceAscii( "$(HOST)", aObj.GetHost() );
2832 String aTarget = aObj.GetFull();
2833 if( aTarget.Len() <= 1 && pArg->eStatus != SVBINDSTATUS_CONNECTING )
2834 aTarget = aObj.GetHost();
2835 if( pArg->nMax )
2837 aTarget += DEFINE_CONST_UNICODE( " (" );
2838 AddNumber_Impl( aTarget, pArg->nMax );
2839 aTarget += ')';
2842 aString.SearchAndReplaceAscii( "$(TARGET)",aTarget );
2843 String aNumber;
2844 AddNumber_Impl( aNumber, pArg->nProgress );
2845 if( pArg->nRate )
2847 aNumber+= DEFINE_CONST_UNICODE( " (" );
2848 AddNumber_Impl( aNumber, (ULONG)pArg->nRate );
2849 aNumber+= DEFINE_CONST_UNICODE( "/s)" );
2851 if( pArg->nMax && pArg->nProgress && pArg->nMax != pArg->nProgress )
2853 aNumber += DEFINE_CONST_UNICODE( " [" );
2854 float aPerc = pArg->nProgress / (float)pArg->nMax;
2855 aNumber += String::CreateFromInt32( (USHORT)(aPerc * 100) );
2856 aNumber += DEFINE_CONST_UNICODE( "%]" );
2858 aString.SearchAndReplaceAscii( "$(BYTE)", aNumber );
2860 return aString;
2864 sal_Bool SfxMedium::IsRemote()
2866 return bRemote;
2869 //------------------------------------------------------------------
2871 void SfxMedium::SetUpdatePickList(sal_Bool bVal)
2873 if(!pImp)
2874 pImp = new SfxMedium_Impl( this );
2875 pImp->bUpdatePickList = bVal;
2877 //------------------------------------------------------------------
2879 sal_Bool SfxMedium::IsUpdatePickList() const
2881 return pImp? pImp->bUpdatePickList: sal_True;
2883 //----------------------------------------------------------------
2885 void SfxMedium::SetDoneLink( const Link& rLink )
2887 pImp->aDoneLink = rLink;
2890 //----------------------------------------------------------------
2892 void SfxMedium::SetDataAvailableLink( const Link& rLink )
2894 pImp->aAvailableLink = rLink;
2897 //----------------------------------------------------------------
2898 void SfxMedium::StartDownload()
2900 GetInStream();
2903 void SfxMedium::DownLoad( const Link& aLink )
2905 SetDoneLink( aLink );
2906 GetInStream();
2907 if ( pInStream && !aLink.IsSet() )
2909 while( !pImp->bDownloadDone )
2910 Application::Yield();
2914 //------------------------------------------------------------------
2915 void SfxMedium::Init_Impl()
2916 /* [Beschreibung]
2917 Setzt in den Logischen Namen eine gueltige ::com::sun::star::util::URL (Falls zuvor ein Filename
2918 drin war) und setzt den physikalschen Namen auf den Filenamen, falls
2919 vorhanden.
2923 Reference< XOutputStream > rOutStream;
2925 // TODO/LATER: handle lifetime of storages
2926 pImp->bDisposeStorage = FALSE;
2928 SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False);
2929 if ( pSalvageItem && !pSalvageItem->GetValue().Len() )
2931 pSalvageItem = NULL;
2932 pSet->ClearItem( SID_DOC_SALVAGE );
2935 if( aLogicName.Len() )
2937 INetURLObject aUrl( aLogicName );
2938 INetProtocol eProt = aUrl.GetProtocol();
2939 if ( eProt == INET_PROT_NOT_VALID )
2941 DBG_ERROR ( "Unknown protocol!" );
2943 else
2945 if ( aUrl.HasMark() )
2947 aLogicName = aUrl.GetURLNoMark( INetURLObject::NO_DECODE );
2948 GetItemSet()->Put( SfxStringItem( SID_JUMPMARK, aUrl.GetMark() ) );
2951 // try to convert the URL into a physical name - but never change a physical name
2952 // physical name may be set if the logical name is changed after construction
2953 if ( !aName.Len() )
2954 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aName );
2955 else {
2956 DBG_ASSERT( pSalvageItem, "Suspicious change of logical name!" );
2961 if ( pSalvageItem && pSalvageItem->GetValue().Len() )
2963 aLogicName = pSalvageItem->GetValue();
2964 DELETEZ( pURLObj );
2965 pImp->m_bSalvageMode = sal_True;
2968 // in case output stream is by mistake here
2969 // clear the reference
2970 SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
2971 if( pOutStreamItem
2972 && ( !( pOutStreamItem->GetValue() >>= rOutStream )
2973 || !aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL ) )
2975 pSet->ClearItem( SID_OUTPUTSTREAM );
2976 DBG_ERROR( "Unexpected Output stream parameter!\n" );
2979 if ( aLogicName.Len() )
2981 // if the logic name is set it should be set in MediaDescriptor as well
2982 SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE );
2983 if ( !pFileNameItem )
2985 // let the ItemSet be created if necessary
2986 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, INetURLObject( aLogicName ).GetMainURL( INetURLObject::NO_DECODE ) ) );
2990 SetIsRemote_Impl();
2993 //------------------------------------------------------------------
2994 SfxMedium::SfxMedium()
2995 : IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
2997 pFilter(0),
2998 pSet(0),
2999 pImp(new SfxMedium_Impl( this ))
3001 Init_Impl();
3003 //------------------------------------------------------------------
3005 SfxMedium::SfxMedium( const SfxMedium& rMedium, sal_Bool bTemporary )
3006 : SvRefBase(),
3007 IMPL_CTOR( sal_True, // bRoot, pURLObj
3008 rMedium.pURLObj ? new INetURLObject(*rMedium.pURLObj) : 0 ),
3009 pImp(new SfxMedium_Impl( this ))
3011 bDirect = rMedium.IsDirect();
3012 nStorOpenMode = rMedium.GetOpenMode();
3013 if ( !bTemporary )
3014 aName = rMedium.aName;
3016 pImp->bIsTemp = bTemporary;
3017 DBG_ASSERT( ! rMedium.pImp->bIsTemp, "Temporaeres Medium darf nicht kopiert werden" );
3018 aLogicName = rMedium.aLogicName;
3019 pSet = rMedium.GetItemSet() ? new SfxItemSet(*rMedium.GetItemSet()) : 0;
3020 pFilter = rMedium.pFilter;
3021 Init_Impl();
3022 if( bTemporary )
3023 CreateTempFile();
3026 //------------------------------------------------------------------
3028 void SfxMedium::UseInteractionHandler( BOOL bUse )
3030 pImp->bAllowDefaultIntHdl = bUse;
3033 //------------------------------------------------------------------
3035 ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >
3036 SfxMedium::GetInteractionHandler()
3038 // if interaction isnt allowed explicitly ... return empty reference!
3039 if ( !pImp->bUseInteractionHandler )
3040 return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
3042 // search a possible existing handler inside cached item set
3043 if ( pSet )
3045 ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xHandler;
3046 SFX_ITEMSET_ARG( pSet, pHandler, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False);
3047 if ( pHandler && (pHandler->GetValue() >>= xHandler) && xHandler.is() )
3048 return xHandler;
3051 // if default interaction isnt allowed explicitly ... return empty reference!
3052 if ( !pImp->bAllowDefaultIntHdl )
3053 return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
3055 // otherwhise return cached default handler ... if it exist.
3056 if ( pImp->xInteraction.is() )
3057 return pImp->xInteraction;
3059 // create default handler and cache it!
3060 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
3061 if ( xFactory.is() )
3063 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 );
3064 return pImp->xInteraction;
3067 return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
3070 //----------------------------------------------------------------
3072 void SfxMedium::SetFilter( const SfxFilter* pFilterP, sal_Bool /*bResetOrig*/ )
3074 pFilter = pFilterP;
3075 pImp->nFileVersion = 0;
3077 //----------------------------------------------------------------
3079 const SfxFilter* SfxMedium::GetOrigFilter( sal_Bool bNotCurrent ) const
3081 return ( pImp->pOrigFilter || bNotCurrent ) ? pImp->pOrigFilter : pFilter;
3083 //----------------------------------------------------------------
3085 void SfxMedium::SetOrigFilter_Impl( const SfxFilter* pOrigFilter )
3087 pImp->pOrigFilter = pOrigFilter;
3089 //------------------------------------------------------------------
3091 void SfxMedium::Close()
3093 if ( pImp->xStorage.is() )
3095 // don't close the streams if they belong to the
3096 // storage
3097 //TODO/MBA: how to?! Do we need the flag?!
3099 const SvStream *pStream = aStorage->GetSvStream();
3100 if ( pStream && pStream == pInStream )
3102 CloseReadStorage_Impl();
3103 pInStream = NULL;
3104 pImp->xInputStream = Reference < XInputStream >();
3105 pImp->xLockBytes.Clear();
3106 if ( pSet )
3107 pSet->ClearItem( SID_INPUTSTREAM );
3108 aStorage->SetDeleteStream( TRUE );
3110 else if ( pStream && pStream == pOutStream )
3112 pOutStream = NULL;
3113 aStorage->SetDeleteStream( TRUE );
3114 } */
3116 CloseStorage();
3119 CloseStreams_Impl();
3121 UnlockFile();
3124 void SfxMedium::CloseAndRelease()
3126 if ( pImp->xStorage.is() )
3128 // don't close the streams if they belong to the
3129 // storage
3130 //TODO/MBA: how to?! Do we need the flag?!
3132 const SvStream *pStream = aStorage->GetSvStream();
3133 if ( pStream && pStream == pInStream )
3135 CloseReadStorage_Impl();
3136 pInStream = NULL;
3137 pImp->xInputStream = Reference < XInputStream >();
3138 pImp->xLockBytes.Clear();
3139 if ( pSet )
3140 pSet->ClearItem( SID_INPUTSTREAM );
3141 aStorage->SetDeleteStream( TRUE );
3143 else if ( pStream && pStream == pOutStream )
3145 pOutStream = NULL;
3146 aStorage->SetDeleteStream( TRUE );
3147 } */
3149 CloseStorage();
3152 CloseAndReleaseStreams_Impl();
3154 UnlockFile();
3157 void SfxMedium::UnlockFile()
3159 if ( pImp->m_bLocked )
3163 pImp->m_bLocked = sal_False;
3164 ::svt::DocumentLockFile aLockFile( aLogicName );
3165 // TODO/LATER: A warning could be shown in case the file is not the own one
3166 aLockFile.RemoveFile();
3168 catch( uno::Exception& )
3173 void SfxMedium::CloseAndReleaseStreams_Impl()
3175 CloseReadStorage_Impl();
3177 uno::Reference< io::XInputStream > xInToClose = pImp->xInputStream;
3178 uno::Reference< io::XOutputStream > xOutToClose;
3179 if ( pImp->xStream.is() )
3180 xOutToClose = pImp->xStream->getOutputStream();
3182 // The probably exsisting SvStream wrappers should be closed first
3183 CloseStreams_Impl();
3185 // in case of salvage mode the storage is based on the streams
3186 if ( !pImp->m_bSalvageMode )
3190 if ( xInToClose.is() )
3191 xInToClose->closeInput();
3192 if ( xOutToClose.is() )
3193 xOutToClose->closeOutput();
3195 catch ( uno::Exception& )
3201 //------------------------------------------------------------------
3202 void SfxMedium::CloseStreams_Impl()
3204 CloseInStream_Impl();
3205 CloseOutStream_Impl();
3207 if ( pSet )
3208 pSet->ClearItem( SID_CONTENT );
3210 pImp->aContent = ::ucbhelper::Content();
3213 //------------------------------------------------------------------
3215 void SfxMedium::RefreshName_Impl()
3217 #if 0 //(dv)
3218 if ( pImp->aContent.get().is() )
3220 String aNameP = pImp->xAnchor->GetViewURL();
3221 pImp->aOrigURL = aNameP;
3222 aLogicName = aNameP;
3223 DELETEZ( pURLObj );
3224 if (aLogicName.Len())
3225 aLogicName = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
3226 SetIsRemote_Impl();
3228 #endif //(dv)
3231 void SfxMedium::SetIsRemote_Impl()
3233 INetURLObject aObj( GetName() );
3234 switch( aObj.GetProtocol() )
3236 case INET_PROT_FTP:
3237 case INET_PROT_HTTP:
3238 case INET_PROT_HTTPS:
3239 case INET_PROT_POP3:
3240 case INET_PROT_NEWS:
3241 case INET_PROT_IMAP:
3242 // case INET_PROT_OUT:
3243 case INET_PROT_VIM:
3244 bRemote = TRUE; break;
3245 default:
3246 bRemote = ( GetName().CompareToAscii( "private:msgid", 13 ) == COMPARE_EQUAL );
3247 break;
3250 // Da Dateien, die Remote geschrieben werden zur Uebertragung auch
3251 // gelesen werden koennen muessen
3252 if( bRemote )
3253 nStorOpenMode |= STREAM_READ;
3258 void SfxMedium::SetName( const String& aNameP, sal_Bool bSetOrigURL )
3260 if( !pImp->aOrigURL.Len() )
3261 pImp->aOrigURL = aLogicName;
3262 if( bSetOrigURL )
3263 pImp->aOrigURL = aNameP;
3264 aLogicName = aNameP;
3265 DELETEZ( pURLObj );
3266 pImp->aContent = ::ucbhelper::Content();
3267 Init_Impl();
3270 //----------------------------------------------------------------
3271 const String& SfxMedium::GetOrigURL() const
3273 return !pImp->aOrigURL.Len() ? (String &)aLogicName : pImp->aOrigURL;
3276 //----------------------------------------------------------------
3278 void SfxMedium::SetPhysicalName_Impl( const String& rNameP )
3280 if ( rNameP != aName )
3282 if( pImp->pTempFile )
3284 delete pImp->pTempFile;
3285 pImp->pTempFile = NULL;
3288 if ( aName.Len() || rNameP.Len() )
3289 pImp->aContent = ::ucbhelper::Content();
3291 aName = rNameP;
3292 bTriedStorage = sal_False;
3293 pImp->bIsStorage = sal_False;
3297 //----------------------------------------------------------------
3298 void SfxMedium::MoveTempTo_Impl( SfxMedium* pMedium )
3300 if ( pMedium && pMedium != this && pImp->pTempFile )
3302 if( pMedium->pImp->pTempFile )
3303 delete pMedium->pImp->pTempFile;
3304 pMedium->pImp->pTempFile = pImp->pTempFile;
3306 pImp->pTempFile->EnableKillingFile( sal_True );
3307 pImp->pTempFile = NULL;
3309 pMedium->aName = pMedium->pImp->pTempFile->GetFileName();
3311 pMedium->CloseInStream();
3312 pMedium->CloseStorage();
3313 pMedium->pImp->aContent = ::ucbhelper::Content();
3317 //------------------------------------------------------------------
3318 void SfxMedium::SetTemporary( sal_Bool bTemp )
3320 pImp->bIsTemp = bTemp;
3323 //------------------------------------------------------------------
3324 sal_Bool SfxMedium::IsTemporary() const
3326 return pImp->bIsTemp;
3329 //------------------------------------------------------------------
3331 sal_Bool SfxMedium::Exists( sal_Bool /*bForceSession*/ )
3333 DBG_ERROR( "Not implemented!" );
3334 return sal_True;
3337 //------------------------------------------------------------------
3339 void SfxMedium::ReOpen()
3341 BOOL bUseInteractionHandler = pImp->bUseInteractionHandler;
3342 pImp->bUseInteractionHandler = FALSE;
3343 GetMedium_Impl();
3344 pImp->bUseInteractionHandler = bUseInteractionHandler;
3347 //------------------------------------------------------------------
3349 void SfxMedium::CompleteReOpen()
3351 // do not use temporary file for reopen and in case of success throw the temporary file away
3352 BOOL bUseInteractionHandler = pImp->bUseInteractionHandler;
3353 pImp->bUseInteractionHandler = FALSE;
3355 ::utl::TempFile* pTmpFile = NULL;
3356 if ( pImp->pTempFile )
3358 pTmpFile = pImp->pTempFile;
3359 pImp->pTempFile = NULL;
3360 aName = String();
3363 GetMedium_Impl();
3365 if ( GetError() )
3367 if ( pImp->pTempFile )
3369 pImp->pTempFile->EnableKillingFile( sal_True );
3370 delete pImp->pTempFile;
3372 pImp->pTempFile = pTmpFile;
3373 if ( pImp->pTempFile )
3374 aName = pImp->pTempFile->GetFileName();
3376 else
3378 pTmpFile->EnableKillingFile( sal_True );
3379 delete pTmpFile;
3383 pImp->bUseInteractionHandler = bUseInteractionHandler;
3386 //------------------------------------------------------------------
3387 SfxMedium::SfxMedium
3389 const String &rName, StreamMode nOpenMode, sal_Bool bDirectP,
3390 const SfxFilter *pFlt, SfxItemSet *pInSet
3392 : IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
3393 pFilter(pFlt),
3394 pSet( pInSet ),
3395 pImp(new SfxMedium_Impl( this ))
3397 aLogicName = rName;
3398 nStorOpenMode = nOpenMode;
3399 bDirect = bDirectP;
3400 Init_Impl();
3404 SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
3405 : IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
3406 pFilter(0),
3407 pSet(0),
3408 pImp(new SfxMedium_Impl( this ))
3410 SfxAllItemSet *pParams = new SfxAllItemSet( SFX_APP()->GetPool() );
3411 pSet = pParams;
3412 TransformParameters( SID_OPENDOC, aArgs, *pParams );
3414 String aFilterName;
3415 SFX_ITEMSET_ARG( pSet, pFilterNameItem, SfxStringItem, SID_FILTER_NAME, sal_False );
3416 if( pFilterNameItem )
3417 aFilterName = pFilterNameItem->GetValue();
3418 pFilter = SFX_APP()->GetFilterMatcher().GetFilter4FilterName( aFilterName );
3420 sal_Bool bSalvage = sal_False;
3421 SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False );
3422 if( pSalvageItem )
3424 // QUESTION: there is some treatment of Salvage in Init_Impl; align!
3425 bSalvage = sal_True;
3426 if ( pSalvageItem->GetValue().Len() )
3428 // if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
3429 // that must be copied here
3431 SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE );
3432 if (!pFileNameItem) throw uno::RuntimeException();
3433 ::rtl::OUString aNewTempFileURL = SfxMedium::CreateTempCopyWithExt( pFileNameItem->GetValue() );
3434 if ( aNewTempFileURL.getLength() )
3436 pSet->Put( SfxStringItem( SID_FILE_NAME, aNewTempFileURL ) );
3437 pSet->ClearItem( SID_INPUTSTREAM );
3438 pSet->ClearItem( SID_STREAM );
3439 pSet->ClearItem( SID_CONTENT );
3441 else
3443 OSL_ENSURE( sal_False, "Can not create a new temporary file for crash recovery!\n" );
3448 BOOL bReadOnly = FALSE;
3449 SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, FALSE );
3450 if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
3451 bReadOnly = TRUE;
3453 SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE );
3454 if (!pFileNameItem) throw uno::RuntimeException();
3455 aLogicName = pFileNameItem->GetValue();
3456 nStorOpenMode = bReadOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
3457 bDirect = FALSE;
3458 Init_Impl();
3462 //------------------------------------------------------------------
3464 SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const String& rBaseURL, const SfxItemSet* p, sal_Bool bRootP )
3465 : IMPL_CTOR( bRootP, 0 ), // bRoot, pURLObj
3466 pSet(0),
3467 pImp( new SfxMedium_Impl( this ))
3469 String aType = SfxFilter::GetTypeFromStorage( rStor );
3470 pFilter = SFX_APP()->GetFilterMatcher().GetFilter4EA( aType );
3471 DBG_ASSERT( pFilter, "No Filter for storage found!" );
3473 Init_Impl();
3474 pImp->xStorage = rStor;
3475 pImp->bDisposeStorage = FALSE;
3477 // always take BaseURL first, could be overwritten by ItemSet
3478 GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
3479 if ( p )
3480 GetItemSet()->Put( *p );
3483 //------------------------------------------------------------------
3485 SfxMedium::~SfxMedium()
3487 /* Attention
3488 Don't enable CancelTransfers() till you know that the writer/web has changed his asynchronous load
3489 behaviour. Otherwhise may StyleSheets inside a html file will be loaded at the right time.
3490 => further the help will be empty then ... #100490#
3492 //CancelTransfers();
3494 // if there is a requirement to clean the backup this is the last possibility to do it
3495 ClearBackup_Impl();
3497 Close();
3499 delete pSet;
3501 if( pImp->bIsTemp && aName.Len() )
3503 String aTemp;
3504 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aTemp ))
3506 DBG_ERROR("Physical name not convertable!");
3509 if ( !::utl::UCBContentHelper::Kill( aTemp ) )
3511 DBG_ERROR("Couldn't remove temporary file!");
3515 pFilter = 0;
3517 delete pURLObj;
3518 delete pImp;
3520 //------------------------------------------------------------------
3522 void SfxMedium::SetItemSet(SfxItemSet *pNewSet)
3524 delete pSet;
3525 pSet = pNewSet;
3527 //------------------------------------------------------------------
3529 void SfxMedium::SetClassFilter( const SvGlobalName & rFilterClass )
3531 bSetFilter = sal_True;
3532 aFilterClass = rFilterClass;
3534 //----------------------------------------------------------------
3536 const INetURLObject& SfxMedium::GetURLObject() const
3538 if( !pURLObj )
3540 SfxMedium* pThis = const_cast < SfxMedium* > (this);
3541 pThis->pURLObj = new INetURLObject( aLogicName );
3542 if ( pThis->pURLObj->HasMark() )
3543 (*pThis->pURLObj) = INetURLObject( aLogicName ).GetURLNoMark();
3546 return *pURLObj;
3549 //----------------------------------------------------------------
3551 const String& SfxMedium::GetPreRedirectedURL() const
3553 return pImp->aPreRedirectionURL;
3555 //----------------------------------------------------------------
3557 sal_uInt32 SfxMedium::GetMIMEAndRedirect( String& /*rName*/ )
3559 /* dv !!!! not needed any longer ?
3560 INetProtocol eProt = GetURLObject().GetProtocol();
3561 if( eProt == INET_PROT_FTP && SvBinding::ShouldUseFtpProxy( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
3563 Any aAny( UCB_Helper::GetProperty( GetContent(), WID_FLAG_IS_FOLDER ) );
3564 sal_Bool bIsFolder = FALSE;
3565 if ( ( aAny >>= bIsFolder ) && bIsFolder )
3566 return ERRCODE_NONE;
3569 GetMedium_Impl();
3570 if( !eError && pImp->xBinding.Is() )
3572 eError = pImp->xBinding->GetMimeType( rName );
3574 // Wir koennen keine Parameter wie CharSets usw.
3575 rName = rName.GetToken( 0, ';' );
3576 if( !eError )
3578 if( !pImp->aPreRedirectionURL.Len() )
3579 pImp->aPreRedirectionURL = aLogicName;
3580 SetName( pImp->xBinding->GetRedirectedURL() );
3582 pImp->aExpireTime = pImp->xBinding->GetExpireDateTime();
3584 return eError;
3586 return 0;
3589 //----------------------------------------------------------------
3591 void SfxMedium::SetReferer( const String& rRefer )
3593 pImp->aReferer = rRefer;
3595 //----------------------------------------------------------------
3597 const String& SfxMedium::GetReferer( ) const
3599 return pImp->aReferer;
3602 //----------------------------------------------------------------
3604 void SfxMedium::SetExpired_Impl( const DateTime& rDateTime )
3606 pImp->aExpireTime = rDateTime;
3608 //----------------------------------------------------------------
3610 sal_Bool SfxMedium::IsExpired() const
3612 return pImp->aExpireTime.IsValid() && pImp->aExpireTime < DateTime();
3614 //----------------------------------------------------------------
3616 void SfxMedium::ForceSynchronStream_Impl( sal_Bool bForce )
3618 if( pInStream )
3620 SvLockBytes* pBytes = pInStream->GetLockBytes();
3621 if( pBytes )
3622 pBytes->SetSynchronMode( bForce );
3624 pImp->bForceSynchron = bForce;
3627 //----------------------------------------------------------------
3628 SfxFrame* SfxMedium::GetLoadTargetFrame() const
3630 return pImp->wLoadTargetFrame;
3632 //----------------------------------------------------------------
3634 void SfxMedium::SetLoadTargetFrame(SfxFrame* pFrame )
3636 pImp->wLoadTargetFrame = pFrame;
3638 //----------------------------------------------------------------
3640 void SfxMedium::SetStorage_Impl( const uno::Reference < embed::XStorage >& rStor )
3642 pImp->xStorage = rStor;
3644 //----------------------------------------------------------------
3646 SfxItemSet* SfxMedium::GetItemSet() const
3648 // this method *must* return an ItemSet, returning NULL can cause crashes
3649 if( !pSet )
3650 ((SfxMedium*)this)->pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
3651 return pSet;
3653 //----------------------------------------------------------------
3655 SvKeyValueIterator* SfxMedium::GetHeaderAttributes_Impl()
3657 if( !pImp->xAttributes.Is() )
3659 pImp->xAttributes = SvKeyValueIteratorRef( new SvKeyValueIterator );
3661 if ( GetContent().is() )
3663 pImp->bIsCharsetInitialized = sal_True;
3667 Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
3668 ::rtl::OUString aContentType;
3669 aAny >>= aContentType;
3671 pImp->xAttributes->Append( SvKeyValue( ::rtl::OUString::createFromAscii( "content-type" ), aContentType ) );
3673 catch ( ::com::sun::star::uno::Exception& )
3679 return pImp->xAttributes;
3681 //----------------------------------------------------------------
3683 SvCompatWeakHdl* SfxMedium::GetHdl()
3685 return pImp->GetHdl();
3688 sal_Bool SfxMedium::IsDownloadDone_Impl()
3690 return pImp->bDownloadDone;
3693 //----------------------------------------------------------------
3695 void SfxMedium::SetDontCreateCancellable( )
3697 pImp->bDontCreateCancellable = sal_True;
3700 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SfxMedium::GetInputStream()
3702 if ( !pImp->xInputStream.is() )
3703 GetMedium_Impl();
3704 return pImp->xInputStream;
3707 const uno::Sequence < util::RevisionTag >& SfxMedium::GetVersionList( bool _bNoReload )
3709 // if the medium has no name, then this medium should represent a new document and can have no version info
3710 if ( ( !_bNoReload || !pImp->m_bVersionsAlreadyLoaded ) && !pImp->aVersions.getLength() &&
3711 ( aName.Len() || aLogicName.Len() ) && GetStorage().is() )
3713 uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
3714 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3715 if ( xReader.is() )
3719 pImp->aVersions = xReader->load( GetStorage() );
3721 catch ( uno::Exception& )
3727 if ( !pImp->m_bVersionsAlreadyLoaded )
3728 pImp->m_bVersionsAlreadyLoaded = sal_True;
3730 return pImp->aVersions;
3733 uno::Sequence < util::RevisionTag > SfxMedium::GetVersionList( const uno::Reference < embed::XStorage >& xStorage )
3735 uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
3736 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3737 if ( xReader.is() )
3741 return xReader->load( xStorage );
3743 catch ( uno::Exception& )
3748 return uno::Sequence < util::RevisionTag >();
3751 sal_uInt16 SfxMedium::AddVersion_Impl( util::RevisionTag& rRevision )
3753 if ( GetStorage().is() )
3755 // Einen eindeutigen Namen f"ur den Stream ermitteln
3756 SvULongs aLongs;
3757 sal_Int32 nLength = pImp->aVersions.getLength();
3758 for ( sal_Int32 m=0; m<nLength; m++ )
3760 sal_uInt32 nVer = (sal_uInt32) String( pImp->aVersions[m].Identifier ).Copy(7).ToInt32();
3761 sal_uInt16 n;
3762 for ( n=0; n<aLongs.Count(); n++ )
3763 if ( nVer<aLongs[n] )
3764 break;
3766 aLongs.Insert( nVer, n );
3769 sal_uInt16 nKey;
3770 for ( nKey=0; nKey<aLongs.Count(); nKey++ )
3771 if ( aLongs[nKey] > ( ULONG ) nKey+1 )
3772 break;
3774 String aRevName = DEFINE_CONST_UNICODE( "Version" );
3775 aRevName += String::CreateFromInt32( nKey + 1 );
3776 pImp->aVersions.realloc( nLength+1 );
3777 rRevision.Identifier = aRevName;
3778 pImp->aVersions[nLength] = rRevision;
3779 return nKey;
3782 return 0;
3785 sal_Bool SfxMedium::RemoveVersion_Impl( const ::rtl::OUString& rName )
3787 if ( !pImp->aVersions.getLength() )
3788 return sal_False;
3790 sal_Int32 nLength = pImp->aVersions.getLength();
3791 for ( sal_Int32 n=0; n<nLength; n++ )
3793 if ( pImp->aVersions[n].Identifier == rName )
3795 for ( sal_Int32 m=n; m<nLength-1; m++ )
3796 pImp->aVersions[m] = pImp->aVersions[m+1];
3797 pImp->aVersions.realloc(nLength-1);
3798 return sal_True;
3802 return sal_False;
3805 sal_Bool SfxMedium::TransferVersionList_Impl( SfxMedium& rMedium )
3807 if ( rMedium.pImp->aVersions.getLength() )
3809 pImp->aVersions = rMedium.pImp->aVersions;
3810 return sal_True;
3813 return sal_False;
3816 sal_Bool SfxMedium::SaveVersionList_Impl( sal_Bool /*bUseXML*/ )
3818 if ( GetStorage().is() )
3820 if ( !pImp->aVersions.getLength() )
3821 return sal_True;
3823 uno::Reference < document::XDocumentRevisionListPersistence > xWriter( comphelper::getProcessServiceFactory()->createInstance(
3824 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3825 if ( xWriter.is() )
3829 xWriter->store( GetStorage(), pImp->aVersions );
3830 return sal_True;
3832 catch ( uno::Exception& )
3838 return sal_False;
3841 //----------------------------------------------------------------
3842 sal_Bool SfxMedium::IsReadOnly()
3844 sal_Bool bReadOnly = sal_False;
3846 // a) ReadOnly filter cant produce read/write contents!
3847 bReadOnly = (
3848 (pFilter ) &&
3849 ((pFilter->GetFilterFlags() & SFX_FILTER_OPENREADONLY) == SFX_FILTER_OPENREADONLY)
3852 // b) if filter allow read/write contents .. check open mode of the storage
3853 if (!bReadOnly)
3854 bReadOnly = !( GetOpenMode() & STREAM_WRITE );
3856 // c) the API can force the readonly state!
3857 if (!bReadOnly)
3859 SFX_ITEMSET_ARG( GetItemSet(), pItem, SfxBoolItem, SID_DOC_READONLY, sal_False);
3860 if (pItem)
3861 bReadOnly = pItem->GetValue();
3864 return bReadOnly;
3867 //----------------------------------------------------------------
3868 void SfxMedium::TryToSwitchToRepairedTemp()
3870 // the medium should be opened in repair mode
3871 SFX_ITEMSET_ARG( GetItemSet(), pRepairItem, SfxBoolItem, SID_REPAIRPACKAGE, FALSE );
3872 if ( pRepairItem && pRepairItem->GetValue() )
3874 DBG_ASSERT( pImp->xStorage.is(), "Possible performance problem" );
3875 if ( GetStorage().is() )
3877 ::utl::TempFile* pTmpFile = new ::utl::TempFile();
3878 pTmpFile->EnableKillingFile( sal_True );
3879 ::rtl::OUString aNewName = pTmpFile->GetFileName();
3881 if( aNewName.getLength() )
3885 uno::Reference < embed::XStorage > xNewStorage = comphelper::OStorageHelper::GetStorageFromURL( aNewName,
3886 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
3887 //SvStorageRef aNewStorage = new SvStorage( sal_True, aNewName, STREAM_WRITE | STREAM_TRUNC, STORAGE_TRANSACTED );
3889 pImp->xStorage->copyToStorage( xNewStorage );
3890 //if ( aNewStorage->GetError() == SVSTREAM_OK )
3892 CloseInStream();
3893 CloseStorage();
3894 if ( pImp->pTempFile )
3895 DELETEZ( pImp->pTempFile );
3897 pImp->pTempFile = pTmpFile;
3898 aName = aNewName;
3901 catch ( uno::Exception& )
3903 //TODO/MBA: error handling
3904 //SetError( aNewStorage->GetError(, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )) );
3907 else
3908 SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3910 if (pImp->pTempFile != pTmpFile)
3911 delete pTmpFile;
3913 else
3914 SetError( ERRCODE_IO_CANTREAD, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3918 //----------------------------------------------------------------
3919 void SfxMedium::CreateTempFile()
3921 if ( pImp->pTempFile )
3923 DELETEZ( pImp->pTempFile );
3924 aName = String();
3927 StreamMode nOpenMode = nStorOpenMode;
3928 BOOL bCopy = ( nStorOpenMode == nOpenMode && ! ( nOpenMode & STREAM_TRUNC ) );
3929 if ( bCopy && !pInStream )
3931 if ( GetContent().is() )
3935 // make sure that the desired file exists before trying to open
3936 SvMemoryStream aStream(0,0);
3937 ::utl::OInputStreamWrapper* pInput = new ::utl::OInputStreamWrapper( aStream );
3938 Reference< XInputStream > xInput( pInput );
3940 InsertCommandArgument aInsertArg;
3941 aInsertArg.Data = xInput;
3943 aInsertArg.ReplaceExisting = sal_False;
3944 Any aCmdArg;
3945 aCmdArg <<= aInsertArg;
3946 pImp->aContent.executeCommand( ::rtl::OUString::createFromAscii( "insert" ), aCmdArg );
3948 catch ( Exception& )
3950 // it is NOT an error when the stream already exists!
3951 GetInStream();
3956 nStorOpenMode = nOpenMode;
3957 ResetError();
3959 pImp->pTempFile = new ::utl::TempFile();
3960 pImp->pTempFile->EnableKillingFile( sal_True );
3961 aName = pImp->pTempFile->GetFileName();
3962 if ( !aName.Len() )
3964 SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3965 return;
3968 if ( bCopy && pInStream )
3970 GetOutStream();
3971 if ( pOutStream )
3973 char *pBuf = new char [8192];
3974 sal_uInt32 nErr = ERRCODE_NONE;
3976 pInStream->Seek(0);
3977 pOutStream->Seek(0);
3979 while( !pInStream->IsEof() && nErr == ERRCODE_NONE )
3981 sal_uInt32 nRead = pInStream->Read( pBuf, 8192 );
3982 nErr = pInStream->GetError();
3983 pOutStream->Write( pBuf, nRead );
3986 delete[] pBuf;
3987 CloseInStream();
3989 CloseOutStream_Impl();
3991 else
3992 CloseInStream();
3994 CloseStorage();
3997 //----------------------------------------------------------------
3998 void SfxMedium::CreateTempFileNoCopy()
4000 if ( pImp->pTempFile )
4001 delete pImp->pTempFile;
4003 pImp->pTempFile = new ::utl::TempFile();
4004 pImp->pTempFile->EnableKillingFile( sal_True );
4005 aName = pImp->pTempFile->GetFileName();
4006 if ( !aName.Len() )
4008 SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
4009 return;
4012 CloseOutStream_Impl();
4013 CloseStorage();
4016 ::rtl::OUString SfxMedium::GetCharset()
4018 if( !pImp->bIsCharsetInitialized )
4020 // Set an error in case there is no content?
4021 if ( GetContent().is() )
4023 pImp->bIsCharsetInitialized = sal_True;
4027 Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
4028 ::rtl::OUString aField;
4029 aAny >>= aField;
4031 ::rtl::OString sContent = ::rtl::OUStringToOString( aField, RTL_TEXTENCODING_ASCII_US );
4032 ByteString sType, sSubType;
4033 INetContentTypeParameterList aParameters;
4035 if( INetContentTypes::parse( sContent, sType, sSubType, &aParameters ) )
4037 const INetContentTypeParameter * pCharset = aParameters.find("charset");
4038 if (pCharset != 0)
4039 pImp->aCharset = pCharset->m_sValue;
4042 catch ( ::com::sun::star::uno::Exception& )
4048 return pImp->aCharset;
4051 void SfxMedium::SetCharset( ::rtl::OUString aChs )
4053 pImp->bIsCharsetInitialized = sal_True;
4054 pImp->aCharset = aChs;
4057 sal_Bool SfxMedium::SignContents_Impl( sal_Bool bScriptingContent )
4059 DBG_ASSERT( GetStorage().is(), "SfxMedium::SignContents_Impl - Storage doesn't exist!" );
4061 sal_Bool bChanges = FALSE;
4063 ::com::sun::star::uno::Reference< ::com::sun::star::security::XDocumentDigitalSignatures > xD(
4064 comphelper::getProcessServiceFactory()->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ) ), ::com::sun::star::uno::UNO_QUERY );
4066 // TODO/LATER: error handling
4067 if ( xD.is() && GetStorage().is() )
4069 sal_Int32 nEncrMode = IsReadOnly() ? embed::ElementModes::READ
4070 : embed::ElementModes::READWRITE;
4074 uno::Reference< embed::XStorage > xMetaInf = GetStorage()->openStorageElement(
4075 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
4076 nEncrMode );
4077 if ( !xMetaInf.is() )
4078 throw uno::RuntimeException();
4080 if ( bScriptingContent )
4082 if ( !IsReadOnly() )
4084 uno::Reference< io::XStream > xStream = xMetaInf->openStreamElement(
4085 xD->getScriptingContentSignatureDefaultStreamName(),
4086 nEncrMode );
4087 if ( !xStream.is() )
4088 throw uno::RuntimeException();
4092 // to leave the stream unencrypted as before
4093 uno::Reference< beans::XPropertySet > xStrmProps( xStream, uno::UNO_QUERY_THROW );
4094 xStrmProps->setPropertyValue(
4095 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) ),
4096 uno::makeAny( (sal_Bool)sal_False ) );
4098 catch ( uno::Exception& )
4101 if ( xD->signScriptingContent( GetLastCommitReadStorage_Impl(), xStream ) )
4103 uno::Reference< embed::XTransactedObject > xTrans( xMetaInf, uno::UNO_QUERY );
4104 xTrans->commit();
4105 Commit();
4106 bChanges = TRUE;
4109 else
4110 xD->showScriptingContentSignatures( GetLastCommitReadStorage_Impl(), uno::Reference< io::XInputStream >() );
4112 else
4114 if ( !IsReadOnly() )
4116 uno::Reference< io::XStream > xStream = xMetaInf->openStreamElement(
4117 xD->getDocumentContentSignatureDefaultStreamName(),
4118 nEncrMode );
4119 if ( !xStream.is() )
4120 throw uno::RuntimeException();
4124 // to leave the stream unencrypted as before
4125 uno::Reference< beans::XPropertySet > xStrmProps( xStream, uno::UNO_QUERY_THROW );
4126 xStrmProps->setPropertyValue(
4127 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) ),
4128 uno::makeAny( (sal_Bool)sal_False ) );
4130 catch ( uno::Exception& )
4133 if ( xD->signDocumentContent( GetLastCommitReadStorage_Impl(), xStream ) )
4135 uno::Reference< embed::XTransactedObject > xTrans( xMetaInf, uno::UNO_QUERY );
4136 xTrans->commit();
4137 Commit();
4138 bChanges = TRUE;
4142 else
4143 xD->showDocumentContentSignatures( GetLastCommitReadStorage_Impl(), uno::Reference< io::XInputStream >() );
4146 catch( uno::Exception& )
4148 OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
4151 return bChanges;
4154 //----------------------------------------------------------------
4155 sal_uInt16 SfxMedium::GetCachedSignatureState_Impl()
4157 return pImp->m_nSignatureState;
4160 //----------------------------------------------------------------
4161 void SfxMedium::SetCachedSignatureState_Impl( sal_uInt16 nState )
4163 pImp->m_nSignatureState = nState;
4166 //----------------------------------------------------------------
4167 sal_Bool SfxMedium::EqualURLs( const ::rtl::OUString& aFirstURL, const ::rtl::OUString& aSecondURL )
4169 sal_Bool bResult = sal_False;
4171 if ( aFirstURL.getLength() && aSecondURL.getLength() )
4173 INetURLObject aFirst( aFirstURL );
4174 INetURLObject aSecond( aSecondURL );
4176 if ( aFirst.GetProtocol() != INET_PROT_NOT_VALID && aSecond.GetProtocol() != INET_PROT_NOT_VALID )
4180 ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get();
4181 if ( !pBroker )
4182 throw uno::RuntimeException();
4184 uno::Reference< ::com::sun::star::ucb::XContentIdentifierFactory > xIdFac
4185 = pBroker->getContentIdentifierFactoryInterface();
4186 if ( !xIdFac.is() )
4187 throw uno::RuntimeException();
4189 uno::Reference< ::com::sun::star::ucb::XContentIdentifier > xIdFirst
4190 = xIdFac->createContentIdentifier( aFirst.GetMainURL( INetURLObject::NO_DECODE ) );
4191 uno::Reference< ::com::sun::star::ucb::XContentIdentifier > xIdSecond
4192 = xIdFac->createContentIdentifier( aSecond.GetMainURL( INetURLObject::NO_DECODE ) );
4194 if ( xIdFirst.is() && xIdSecond.is() )
4196 uno::Reference< ::com::sun::star::ucb::XContentProvider > xProvider =
4197 pBroker->getContentProviderInterface();
4198 if ( !xProvider.is() )
4199 throw uno::RuntimeException();
4200 bResult = !xProvider->compareContentIds( xIdFirst, xIdSecond );
4203 catch( uno::Exception& )
4205 OSL_ENSURE( sal_False, "Can't compare URL's, treat as different!\n" );
4210 return bResult;
4213 BOOL SfxMedium::HasStorage_Impl() const
4215 return pImp->xStorage.is();
4218 BOOL SfxMedium::IsOpen() const
4220 return pInStream || pOutStream || pImp->xStorage.is();
4223 ::rtl::OUString SfxMedium::CreateTempCopyWithExt( const ::rtl::OUString& aURL )
4225 ::rtl::OUString aResult;
4227 if ( aURL.getLength() )
4229 sal_Int32 nPrefixLen = aURL.lastIndexOf( '.' );
4230 String aExt = ( nPrefixLen == -1 ) ? String() : String( aURL.copy( nPrefixLen ) );
4232 ::rtl::OUString aNewTempFileURL = ::utl::TempFile( String(), &aExt ).GetURL();
4233 if ( aNewTempFileURL.getLength() )
4235 INetURLObject aSource( aURL );
4236 INetURLObject aDest( aNewTempFileURL );
4237 ::rtl::OUString aFileName = aDest.getName( INetURLObject::LAST_SEGMENT,
4238 true,
4239 INetURLObject::DECODE_WITH_CHARSET );
4240 if ( aFileName.getLength() && aDest.removeSegment() )
4244 uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
4245 ::ucbhelper::Content aTargetContent( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
4246 ::ucbhelper::Content aSourceContent( aSource.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
4247 if ( aTargetContent.transferContent( aSourceContent,
4248 ::ucbhelper::InsertOperation_COPY,
4249 aFileName,
4250 NameClash::OVERWRITE ) )
4252 // Success
4253 aResult = aNewTempFileURL;
4256 catch( uno::Exception& )
4262 return aResult;
4265 ::rtl::OUString SfxMedium::SwitchDocumentToTempFile()
4267 // the method returns empty string in case of failure
4268 ::rtl::OUString aResult;
4269 ::rtl::OUString aOrigURL = aLogicName;
4271 if ( aOrigURL.getLength() )
4273 sal_Int32 nPrefixLen = aOrigURL.lastIndexOf( '.' );
4274 String aExt = ( nPrefixLen == -1 ) ? String() : String( aOrigURL.copy( nPrefixLen ) );
4275 ::rtl::OUString aNewURL = ::utl::TempFile( String(), &aExt ).GetURL();
4277 // TODO/LATER: In future the aLogicName should be set to shared folder URL
4278 // and a temporary file should be created. Transport_Impl should be impossible then.
4279 if ( aNewURL.getLength() )
4281 uno::Reference< embed::XStorage > xStorage = GetStorage();
4282 uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
4284 if ( xOptStorage.is() )
4286 // TODO/LATER: reuse the pImp->pTempFile if it already exists
4287 CanDisposeStorage_Impl( sal_False );
4288 Close();
4289 SetPhysicalName_Impl( String() );
4290 SetName( aNewURL );
4292 // remove the readonly state
4293 sal_Bool bWasReadonly = sal_False;
4294 nStorOpenMode = SFX_STREAM_READWRITE;
4295 SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, FALSE );
4296 if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
4297 bWasReadonly = sal_True;
4298 GetItemSet()->ClearItem( SID_DOC_READONLY );
4300 GetMedium_Impl();
4301 LockOrigFileOnDemand( sal_False, sal_False );
4302 CreateTempFile();
4303 GetMedium_Impl();
4305 if ( pImp->xStream.is() )
4309 xOptStorage->writeAndAttachToStream( pImp->xStream );
4310 pImp->xStorage = xStorage;
4311 aResult = aNewURL;
4313 catch( uno::Exception& )
4317 if ( !aResult.getLength() )
4319 Close();
4320 SetPhysicalName_Impl( String() );
4321 SetName( aOrigURL );
4322 if ( bWasReadonly )
4324 // set the readonly state back
4325 nStorOpenMode = SFX_STREAM_READONLY;
4326 GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY, sal_True));
4328 GetMedium_Impl();
4329 pImp->xStorage = xStorage;
4335 return aResult;
4338 sal_Bool SfxMedium::SwitchDocumentToFile( ::rtl::OUString aURL )
4340 // the method is only for storage based documents
4341 sal_Bool bResult = sal_False;
4342 ::rtl::OUString aOrigURL = aLogicName;
4344 if ( aURL.getLength() && aOrigURL.getLength() )
4346 uno::Reference< embed::XStorage > xStorage = GetStorage();
4347 uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
4349 if ( xOptStorage.is() )
4351 // TODO/LATER: reuse the pImp->pTempFile if it already exists
4352 CanDisposeStorage_Impl( sal_False );
4353 Close();
4354 SetPhysicalName_Impl( String() );
4355 SetName( aURL );
4357 // open the temporary file based document
4358 GetMedium_Impl();
4359 LockOrigFileOnDemand( sal_False, sal_False );
4360 CreateTempFile();
4361 GetMedium_Impl();
4363 if ( pImp->xStream.is() )
4367 uno::Reference< io::XTruncate > xTruncate( pImp->xStream, uno::UNO_QUERY_THROW );
4368 if ( xTruncate.is() )
4369 xTruncate->truncate();
4371 xOptStorage->writeAndAttachToStream( pImp->xStream );
4372 pImp->xStorage = xStorage;
4373 bResult = sal_True;
4375 catch( uno::Exception& )
4379 if ( !bResult )
4381 Close();
4382 SetPhysicalName_Impl( String() );
4383 SetName( aOrigURL );
4384 GetMedium_Impl();
4385 pImp->xStorage = xStorage;
4390 return bResult;