xref: /trunk/main/sfx2/source/doc/docfile.cxx (revision 15289133)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26 #include <sfx2/docfile.hxx>
27 #include "sfx2/signaturestate.hxx"
28 
29 #include <uno/mapping.hxx>
30 #include <com/sun/star/task/XInteractionHandler.hpp>
31 #include <com/sun/star/uno/Reference.h>
32 #include <com/sun/star/ucb/XContent.hpp>
33 #include <com/sun/star/document/XDocumentRevisionListPersistence.hpp>
34 #include <com/sun/star/document/LockedDocumentRequest.hpp>
35 #include <com/sun/star/document/OwnLockOnDocumentRequest.hpp>
36 #include <com/sun/star/document/LockedOnSavingRequest.hpp>
37 #include <com/sun/star/document/LockFileIgnoreRequest.hpp>
38 #include <com/sun/star/document/ChangedByOthersRequest.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/embed/XTransactedObject.hpp>
41 #include <com/sun/star/embed/ElementModes.hpp>
42 #include <com/sun/star/embed/UseBackupException.hpp>
43 #include <com/sun/star/embed/XOptimizedStorage.hpp>
44 #include <com/sun/star/ucb/InteractiveIOException.hpp>
45 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
46 #include <com/sun/star/ucb/CommandFailedException.hpp>
47 #include <com/sun/star/ucb/CommandAbortedException.hpp>
48 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
49 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
50 #include <com/sun/star/ucb/XContentProvider.hpp>
51 #include <com/sun/star/ucb/XProgressHandler.hpp>
52 #include <com/sun/star/ucb/XCommandInfo.hpp>
53 #include <com/sun/star/ucb/Lock.hpp>
54 #include <com/sun/star/ucb/InteractiveLockingLockNotAvailableException.hpp>
55 #include <com/sun/star/ucb/InteractiveLockingLockedException.hpp>
56 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
57 #include <com/sun/star/util/XArchiver.hpp>
58 #include <com/sun/star/io/XOutputStream.hpp>
59 #include <com/sun/star/io/XInputStream.hpp>
60 #include <com/sun/star/io/XTruncate.hpp>
61 #include <com/sun/star/io/XStreamListener.hpp>
62 #include <com/sun/star/io/XSeekable.hpp>
63 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
64 #include <com/sun/star/lang/XInitialization.hpp>
65 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
66 #include <com/sun/star/ucb/NameClash.hpp>
67 #include <com/sun/star/ucb/TransferInfo.hpp>
68 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
69 #include <com/sun/star/ucb/OpenMode.hpp>
70 #include <com/sun/star/ucb/NameClashException.hpp>
71 #include <com/sun/star/logging/XSimpleLogRing.hpp>
72 #include <cppuhelper/implbase1.hxx>
73 #include <com/sun/star/beans/PropertyValue.hpp>
74 #ifndef _COM_SUN_STAR_SECURITY_DOCUMENTSIGNATURESINFORMATION_HPP_
75 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
76 #endif
77 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
78 #include <tools/zcodec.hxx>
79 #include <tools/cachestr.hxx>
80 #include <tools/urlobj.hxx>
81 #include <unotools/tempfile.hxx>
82 #include <comphelper/processfactory.hxx>
83 #include <comphelper/componentcontext.hxx>
84 #include <comphelper/interaction.hxx>
85 #include <framework/interaction.hxx>
86 #include <unotools/streamhelper.hxx>
87 #include <unotools/localedatawrapper.hxx>
88 #ifndef _MSGBOX_HXX //autogen
89 #include <vcl/msgbox.hxx>
90 #endif
91 #include <svl/stritem.hxx>
92 #include <svl/eitem.hxx>
93 #include <svl/lckbitem.hxx>
94 #include <svtools/sfxecode.hxx>
95 #include <svl/itemset.hxx>
96 #include <svl/intitem.hxx>
97 #include <svtools/svparser.hxx> // SvKeyValue
98 #include <cppuhelper/weakref.hxx>
99 #include <cppuhelper/implbase1.hxx>
100 
101 #define _SVSTDARR_ULONGS
102 #define _SVSTDARR_STRINGSDTOR
103 #include <svl/svstdarr.hxx>
104 
105 #include <unotools/streamwrap.hxx>
106 
107 #include <rtl/logfile.hxx>
108 #include <osl/file.hxx>
109 
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;
115 
116 #include <comphelper/storagehelper.hxx>
117 #include <comphelper/mediadescriptor.hxx>
118 #include <comphelper/configurationhelper.hxx>
119 #include <comphelper/docpasswordhelper.hxx>
120 #include <tools/urlobj.hxx>
121 #include <tools/inetmime.hxx>
122 #include <unotools/ucblockbytes.hxx>
123 #include <unotools/pathoptions.hxx>
124 #include <svtools/asynclink.hxx>
125 #include <svl/inettype.hxx>
126 #include <ucbhelper/contentbroker.hxx>
127 #include <ucbhelper/commandenvironment.hxx>
128 #include <unotools/localfilehelper.hxx>
129 #include <unotools/ucbstreamhelper.hxx>
130 #include <unotools/ucbhelper.hxx>
131 #include <unotools/progresshandlerwrap.hxx>
132 #include <ucbhelper/content.hxx>
133 #include <ucbhelper/interactionrequest.hxx>
134 #include <sot/stg.hxx>
135 #include <unotools/saveopt.hxx>
136 #include <svl/documentlockfile.hxx>
137 
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 "sfx2/sfxresid.hxx"
149 #include <sfx2/appuno.hxx>
150 
151 //#include "xmlversion.hxx"
152 
153 #define MAX_REDIRECT 5
154 
155 
156 sal_Bool IsReadonlyAccordingACL( const sal_Unicode* pFilePath );
157 
158 //==========================================================
159 namespace {
160 
161 static const sal_Int8 LOCK_UI_NOLOCK = 0;
162 static const sal_Int8 LOCK_UI_SUCCEEDED = 1;
163 static const sal_Int8 LOCK_UI_TRY = 2;
164 
165 //----------------------------------------------------------------
IsSystemFileLockingUsed()166 sal_Bool IsSystemFileLockingUsed()
167 {
168     // check whether system file locking has been used, the default value is false
169     sal_Bool bUseSystemLock = sal_False;
170     try
171     {
172 
173         uno::Reference< uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig(
174                             ::comphelper::getProcessServiceFactory(),
175                             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
176                             ::comphelper::ConfigurationHelper::E_STANDARD );
177         if ( !xCommonConfig.is() )
178             throw uno::RuntimeException();
179 
180         ::comphelper::ConfigurationHelper::readRelativeKey(
181                 xCommonConfig,
182                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
183                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentSystemFileLocking" ) ) ) >>= bUseSystemLock;
184     }
185     catch( const uno::Exception& )
186     {
187     }
188 
189     return bUseSystemLock;
190 }
191 
192 //----------------------------------------------------------------
IsOOoLockFileUsed()193 sal_Bool IsOOoLockFileUsed()
194 {
195     // check whether system file locking has been used, the default value is false
196     sal_Bool bOOoLockFileUsed = sal_False;
197     try
198     {
199 
200         uno::Reference< uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig(
201                             ::comphelper::getProcessServiceFactory(),
202                             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
203                             ::comphelper::ConfigurationHelper::E_STANDARD );
204         if ( !xCommonConfig.is() )
205             throw uno::RuntimeException();
206 
207         ::comphelper::ConfigurationHelper::readRelativeKey(
208                 xCommonConfig,
209                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
210                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentOOoLockFile" ) ) ) >>= bOOoLockFileUsed;
211     }
212     catch( const uno::Exception& )
213     {
214     }
215 
216     return bOOoLockFileUsed;
217 }
218 
219 } // anonymous namespace
220 //==========================================================
221 
222 
223 //----------------------------------------------------------------
224 class SfxMediumHandler_Impl : public ::cppu::WeakImplHelper1< com::sun::star::task::XInteractionHandler >
225 {
226     com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > m_xInter;
227 
228 public:
229     virtual void SAL_CALL handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& xRequest )
230             throw( com::sun::star::uno::RuntimeException );
231 
SfxMediumHandler_Impl(com::sun::star::uno::Reference<com::sun::star::task::XInteractionHandler> xInteraction)232     SfxMediumHandler_Impl( com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > xInteraction )
233         : m_xInter( xInteraction )
234         {}
235 
236     ~SfxMediumHandler_Impl();
237 };
238 
239 //----------------------------------------------------------------
~SfxMediumHandler_Impl()240 SfxMediumHandler_Impl::~SfxMediumHandler_Impl()
241 {
242 }
243 
244 //----------------------------------------------------------------
handle(const com::sun::star::uno::Reference<com::sun::star::task::XInteractionRequest> & xRequest)245 void SAL_CALL SfxMediumHandler_Impl::handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& xRequest )
246         throw( com::sun::star::uno::RuntimeException )
247 {
248 	if( !m_xInter.is() )
249 		return;
250 
251     com::sun::star::uno::Any aRequest = xRequest->getRequest();
252     com::sun::star::ucb::InteractiveIOException aIoException;
253     com::sun::star::ucb::UnsupportedDataSinkException aSinkException;
254     if ( (aRequest >>= aIoException) && ( aIoException.Code == IOErrorCode_ACCESS_DENIED || aIoException.Code == IOErrorCode_LOCKING_VIOLATION ) )
255         return;
256     else
257     if ( aRequest >>= aSinkException )
258         return;
259     else
260         m_xInter->handle( xRequest );
261 }
262 
263 //----------------------------------------------------------------
264 class SfxMedium_Impl : public SvCompatWeakBase
265 {
266 public:
267     ::ucbhelper::Content aContent;
268     sal_Bool bUpdatePickList : 1;
269     sal_Bool bIsTemp        : 1;
270     sal_Bool bForceSynchron : 1;
271     sal_Bool bDownloadDone          : 1;
272     sal_Bool bDontCallDoneLinkOnSharingError : 1;
273     sal_Bool bIsStorage: 1;
274     sal_Bool bUseInteractionHandler: 1;
275     sal_Bool bAllowDefaultIntHdl: 1;
276     sal_Bool bIsCharsetInitialized: 1;
277     sal_Bool bDisposeStorage: 1;
278     sal_Bool bStorageBasedOnInStream: 1;
279     sal_Bool m_bSalvageMode: 1;
280     sal_Bool m_bVersionsAlreadyLoaded: 1;
281     sal_Bool m_bLocked: 1;
282     sal_Bool m_bGotDateTime: 1;
283 
284     uno::Reference < embed::XStorage > xStorage;
285 
286     SfxMedium*       pAntiImpl;
287 
288     long             nFileVersion;
289 
290     const SfxFilter* pOrigFilter;
291     String           aOrigURL;
292     String           aPreRedirectionURL;
293     String           aReferer;
294     DateTime         aExpireTime;
295     SfxFrameWeak     wLoadTargetFrame;
296     SvKeyValueIteratorRef xAttributes;
297 
298     svtools::AsynchronLink  aDoneLink;
299     svtools::AsynchronLink  aAvailableLink;
300 
301     uno::Sequence < util::RevisionTag > aVersions;
302 
303     ::utl::TempFile*           pTempFile;
304 
305     uno::Reference < embed::XStorage > m_xZipStorage;
306     Reference < XInputStream > xInputStream;
307     Reference < XStream > xStream;
308 
309     uno::Reference< io::XStream > m_xLockingStream;
310 
311 	sal_uInt32					nLastStorageError;
312 	::rtl::OUString				aCharset;
313 
314     ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xInteraction;
315 
316     ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xCredentialInteraction;
317 
318 	sal_Bool 		m_bRemoveBackup;
319 	::rtl::OUString m_aBackupURL;
320 
321 	// the following member is changed and makes sense only during saving
322 	// TODO/LATER: in future the signature state should be controlled by the medium not by the document
323 	//             in this case the member will hold this information
324 	sal_uInt16		m_nSignatureState;
325 
326     util::DateTime m_aDateTime;
327 
328     uno::Reference< logging::XSimpleLogRing > m_xLogRing;
329 
330     SfxMedium_Impl( SfxMedium* pAntiImplP );
331     ~SfxMedium_Impl();
332 };
333 
DataAvailable_Impl()334 void SfxMedium::DataAvailable_Impl()
335 {
336     pImp->aAvailableLink.ClearPendingCall();
337     pImp->aAvailableLink.Call( NULL );
338 }
339 
Cancel_Impl()340 void SfxMedium::Cancel_Impl()
341 {
342     SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
343 }
344 
345 //------------------------------------------------------------------
SfxMedium_Impl(SfxMedium * pAntiImplP)346 SfxMedium_Impl::SfxMedium_Impl( SfxMedium* pAntiImplP )
347  :  SvCompatWeakBase( pAntiImplP ),
348     bUpdatePickList(sal_True),
349     bIsTemp( sal_False ),
350     bForceSynchron( sal_False ),
351     bDownloadDone( sal_True ),
352     bDontCallDoneLinkOnSharingError( sal_False ),
353     bIsStorage( sal_False ),
354     bUseInteractionHandler( sal_True ),
355     bAllowDefaultIntHdl( sal_False ),
356     bIsCharsetInitialized( sal_False ),
357     bStorageBasedOnInStream( sal_False ),
358     m_bSalvageMode( sal_False ),
359     m_bVersionsAlreadyLoaded( sal_False ),
360     m_bLocked( sal_False ),
361     m_bGotDateTime( sal_False ),
362     pAntiImpl( pAntiImplP ),
363     nFileVersion( 0 ),
364     pOrigFilter( 0 ),
365     aExpireTime( Date() + 10, Time() ),
366     pTempFile( NULL ),
367     nLastStorageError( 0 ),
368     m_bRemoveBackup( sal_False ),
369     m_nSignatureState( SIGNATURESTATE_NOSIGNATURES )
370 {
371     aDoneLink.CreateMutex();
372 }
373 
374 //------------------------------------------------------------------
~SfxMedium_Impl()375 SfxMedium_Impl::~SfxMedium_Impl()
376 {
377 
378     aDoneLink.ClearPendingCall();
379     aAvailableLink.ClearPendingCall();
380 
381     if ( pTempFile )
382         delete pTempFile;
383 }
384 
385 //================================================================
386 
387 #define IMPL_CTOR(rootVal,URLVal)			\
388      eError( SVSTREAM_OK ),                 \
389                                             \
390      bDirect( sal_False ),                  \
391      bRoot( rootVal ),						\
392      bSetFilter( sal_False ),               \
393      bTriedStorage( sal_False ),            \
394                                             \
395      nStorOpenMode( SFX_STREAM_READWRITE ), \
396      pURLObj( URLVal ),						\
397      pInStream(0),                          \
398      pOutStream( 0 )
399 
400 //------------------------------------------------------------------
ResetError()401 void SfxMedium::ResetError()
402 {
403     eError = SVSTREAM_OK;
404     if( pInStream )
405         pInStream->ResetError();
406     if( pOutStream )
407         pOutStream->ResetError();
408 }
409 
410 //------------------------------------------------------------------
GetLastStorageCreationState()411 sal_uInt32 SfxMedium::GetLastStorageCreationState()
412 {
413 	return pImp->nLastStorageError;
414 }
415 
416 //------------------------------------------------------------------
AddLog(const::rtl::OUString & aMessage)417 void SfxMedium::AddLog( const ::rtl::OUString& aMessage )
418 {
419     if ( !pImp->m_xLogRing.is() )
420     {
421         try
422         {
423             ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
424             if ( aContext.is() )
425                 pImp->m_xLogRing.set( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), UNO_QUERY_THROW );
426         }
427         catch( uno::Exception& )
428         {}
429     }
430 
431     if ( pImp->m_xLogRing.is() )
432         pImp->m_xLogRing->logString( aMessage );
433 }
434 
435 //------------------------------------------------------------------
SetError(sal_uInt32 nError,const::rtl::OUString & aLogMessage)436 void SfxMedium::SetError( sal_uInt32 nError, const ::rtl::OUString& aLogMessage )
437 {
438     eError = nError;
439     if ( eError != ERRCODE_NONE && aLogMessage.getLength() )
440         AddLog( aLogMessage );
441 }
442 
443 //------------------------------------------------------------------
GetErrorCode() const444 sal_uInt32 SfxMedium::GetErrorCode() const
445 {
446     sal_uInt32 lError=eError;
447     if(!lError && pInStream)
448         lError=pInStream->GetErrorCode();
449     if(!lError && pOutStream)
450         lError=pOutStream->GetErrorCode();
451     return lError;
452 }
453 
454 //------------------------------------------------------------------
CheckFileDate(const util::DateTime & aInitDate)455 void SfxMedium::CheckFileDate( const util::DateTime& aInitDate )
456 {
457     GetInitFileDate( sal_True );
458     if ( pImp->m_aDateTime.Seconds != aInitDate.Seconds
459       || pImp->m_aDateTime.Minutes != aInitDate.Minutes
460       || pImp->m_aDateTime.Hours != aInitDate.Hours
461       || pImp->m_aDateTime.Day != aInitDate.Day
462       || pImp->m_aDateTime.Month != aInitDate.Month
463       || pImp->m_aDateTime.Year != aInitDate.Year )
464     {
465         uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
466 
467         if ( xHandler.is() )
468         {
469             try
470             {
471                 ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
472                     document::ChangedByOthersRequest() ) );
473                 uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
474                 aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
475                 aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
476                 xInteractionRequestImpl->setContinuations( aContinuations );
477 
478                 xHandler->handle( xInteractionRequestImpl.get() );
479 
480                 ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
481                 if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
482                 {
483                     SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
484                 }
485             }
486             catch ( uno::Exception& )
487             {}
488         }
489     }
490 }
491 
492 //------------------------------------------------------------------
DocNeedsFileDateCheck()493 sal_Bool SfxMedium::DocNeedsFileDateCheck()
494 {
495     ::rtl::OUString aScheme =  INetURLObject::GetScheme( GetURLObject().GetProtocol() );
496     sal_Bool bIsWebDAV = ( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) ||
497                                   aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) );
498     return ( !IsReadOnly() &&
499              ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) || bIsWebDAV ) );
500 }
501 
502 //------------------------------------------------------------------
GetInitFileDate(sal_Bool bIgnoreOldValue)503 util::DateTime SfxMedium::GetInitFileDate( sal_Bool bIgnoreOldValue )
504 {
505     if ( ( bIgnoreOldValue || !pImp->m_bGotDateTime ) && aLogicName.Len() )
506     {
507         try
508         {
509             uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
510             ::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv );
511 
512             aContent.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "DateModified" )) ) >>= pImp->m_aDateTime;
513             pImp->m_bGotDateTime = sal_True;
514         }
515         catch ( ::com::sun::star::uno::Exception& )
516         {
517         }
518     }
519 
520     return pImp->m_aDateTime;
521 }
522 
523 //------------------------------------------------------------------
GetContent() const524 Reference < XContent > SfxMedium::GetContent() const
525 {
526     if ( !pImp->aContent.get().is() )
527     {
528 		Reference < ::com::sun::star::ucb::XContent > xContent;
529 	    Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
530 
531         SFX_ITEMSET_ARG( pSet, pItem, SfxUnoAnyItem, SID_CONTENT, sal_False);
532         if ( pItem )
533             pItem->GetValue() >>= xContent;
534 
535 		if ( xContent.is() )
536 		{
537 			try
538 			{
539 				pImp->aContent = ::ucbhelper::Content( xContent, xEnv );
540 			}
541 			catch ( Exception& )
542 			{
543 			}
544 		}
545 		else
546 		{
547 			// TODO: DBG_ERROR("SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
548 			String aURL;
549 	        if ( aName.Len() )
550 	        	::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL );
551 	        else if ( aLogicName.Len() )
552 	            aURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
553 			if ( aURL.Len() )
554 	            ::ucbhelper::Content::create( aURL, xEnv, pImp->aContent );
555 		}
556     }
557 
558     return pImp->aContent.get();
559 }
560 
561 //------------------------------------------------------------------
GetBaseURL(bool bForSaving)562 ::rtl::OUString SfxMedium::GetBaseURL( bool bForSaving )
563 {
564     ::rtl::OUString aBaseURL;
565     const SfxStringItem* pBaseURLItem = static_cast<const SfxStringItem*>( GetItemSet()->GetItem(SID_DOC_BASEURL) );
566     if ( pBaseURLItem )
567         aBaseURL = pBaseURLItem->GetValue();
568     else if ( GetContent().is() )
569     {
570         try
571         {
572             Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI" )) );
573             aAny >>= aBaseURL;
574         }
575         catch ( ::com::sun::star::uno::Exception& )
576         {
577         }
578 
579         if ( !aBaseURL.getLength() )
580             aBaseURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
581     }
582 
583     if ( bForSaving )
584     {
585         SvtSaveOptions aOpt;
586         sal_Bool bIsRemote = IsRemote();
587         if( (bIsRemote && !aOpt.IsSaveRelINet()) || (!bRemote && !aOpt.IsSaveRelFSys()) )
588             return ::rtl::OUString();
589     }
590 
591     return aBaseURL;
592 }
593 
594 //------------------------------------------------------------------
GetInStream()595 SvStream* SfxMedium::GetInStream()
596 {
597     if ( pInStream )
598     {
599         return pInStream;
600     }
601 
602     if ( pImp->pTempFile )
603     {
604         pInStream = new SvFileStream( aName, nStorOpenMode );
605 
606         eError = pInStream->GetError();
607 
608         if( !eError && (nStorOpenMode & STREAM_WRITE)
609                     && ! pInStream->IsWritable() )
610         {
611             eError = ERRCODE_IO_ACCESSDENIED;
612             delete pInStream;
613             pInStream = NULL;
614         }
615         else
616         {
617             return pInStream;
618         }
619     }
620 
621     GetMedium_Impl();
622 
623     if ( GetError() )
624     {
625         return NULL;
626     }
627 
628     return pInStream;
629 }
630 
631 //------------------------------------------------------------------
CloseInStream()632 void SfxMedium::CloseInStream()
633 {
634     CloseInStream_Impl();
635 }
636 
CloseInStream_Impl()637 void SfxMedium::CloseInStream_Impl()
638 {
639     // if there is a storage based on the InStream, we have to
640     // close the storage, too, because otherwise the storage
641     // would use an invalid ( deleted ) stream.
642     if ( pInStream && pImp->xStorage.is() )
643     {
644     	if ( pImp->bStorageBasedOnInStream )
645             CloseStorage();
646     }
647 
648     if ( pInStream && !GetContent().is() )
649     {
650         CreateTempFile( sal_True );
651         return;
652     }
653 
654     DELETEZ( pInStream );
655     if ( pSet )
656         pSet->ClearItem( SID_INPUTSTREAM );
657 
658 	CloseZipStorage_Impl();
659 	pImp->xInputStream = uno::Reference< io::XInputStream >();
660 
661 	if ( !pOutStream )
662 	{
663 		// output part of the stream is not used so the whole stream can be closed
664         // TODO/LATER: is it correct?
665 		pImp->xStream = uno::Reference< io::XStream >();
666 		if ( pSet )
667 			pSet->ClearItem( SID_STREAM );
668 	}
669 }
670 
671 //------------------------------------------------------------------
GetOutStream()672 SvStream* SfxMedium::GetOutStream()
673 {
674     if ( !pOutStream )
675     {
676         // Create a temp. file if there is none because we always
677         // need one.
678         CreateTempFile( sal_False );
679 
680         if ( pImp->pTempFile )
681         {
682             pOutStream = new SvFileStream( aName, STREAM_STD_READWRITE );
683             CloseStorage();
684         }
685     }
686 
687     return pOutStream;
688 }
689 
690 //------------------------------------------------------------------
CloseOutStream()691 sal_Bool SfxMedium::CloseOutStream()
692 {
693     CloseOutStream_Impl();
694     return sal_True;
695 }
696 
CloseOutStream_Impl()697 sal_Bool SfxMedium::CloseOutStream_Impl()
698 {
699     if ( pOutStream )
700     {
701         // if there is a storage based on the OutStream, we have to
702         // close the storage, too, because otherwise the storage
703         // would use an invalid ( deleted ) stream.
704         //TODO/MBA: how to deal with this?!
705         //maybe we need a new flag when the storage was created from the outstream
706         if ( pImp->xStorage.is() )
707         {
708             //const SvStream *pStorage = aStorage->GetSvStream();
709             //if ( pStorage == pOutStream )
710                 CloseStorage();
711         }
712 
713         delete pOutStream;
714         pOutStream = NULL;
715     }
716 
717 	if ( !pInStream )
718 	{
719 		// input part of the stream is not used so the whole stream can be closed
720         // TODO/LATER: is it correct?
721 		pImp->xStream = uno::Reference< io::XStream >();
722     	if ( pSet )
723 			pSet->ClearItem( SID_STREAM );
724 	}
725 
726     return sal_True;
727 }
728 
729 //------------------------------------------------------------------
GetPhysicalName() const730 const String& SfxMedium::GetPhysicalName() const
731 {
732     if ( !aName.Len() && aLogicName.Len() )
733         (( SfxMedium*)this)->CreateFileStream();
734 
735     // return the name then
736     return aName;
737 }
738 
739 //------------------------------------------------------------------
CreateFileStream()740 void SfxMedium::CreateFileStream()
741 {
742     ForceSynchronStream_Impl( sal_True );
743     GetInStream();
744     if( pInStream )
745     {
746         CreateTempFile( sal_False );
747         pImp->bIsTemp = sal_True;
748         CloseInStream_Impl();
749     }
750 }
751 
752 //------------------------------------------------------------------
Commit()753 sal_Bool SfxMedium::Commit()
754 {
755     if( pImp->xStorage.is() )
756 		StorageCommit_Impl();
757     else if( pOutStream  )
758         pOutStream->Flush();
759     else if( pInStream  )
760         pInStream->Flush();
761 
762     if ( GetError() == SVSTREAM_OK )
763 	{
764 		// does something only in case there is a temporary file ( means aName points to different location than aLogicName )
765         Transfer_Impl();
766 	}
767 
768     sal_Bool bResult = ( GetError() == SVSTREAM_OK );
769 
770     if ( bResult && DocNeedsFileDateCheck() )
771         GetInitFileDate( sal_True );
772 
773     // remove truncation mode from the flags
774     nStorOpenMode &= (~STREAM_TRUNC);
775     return bResult;
776 }
777 
778 //------------------------------------------------------------------
IsStorage()779 sal_Bool SfxMedium::IsStorage()
780 {
781     if ( pImp->xStorage.is() )
782         return sal_True;
783 
784     if ( bTriedStorage )
785         return pImp->bIsStorage;
786 
787     if ( pImp->pTempFile )
788     {
789 		String aURL;
790 		if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL ) )
791         {
792 			DBG_ERROR("Physical name not convertable!");
793         }
794         pImp->bIsStorage = SotStorage::IsStorageFile( aURL ) && !SotStorage::IsOLEStorage( aURL);
795         if ( !pImp->bIsStorage )
796             bTriedStorage = sal_True;
797     }
798     else if ( GetInStream() )
799     {
800         pImp->bIsStorage = SotStorage::IsStorageFile( pInStream ) && !SotStorage::IsOLEStorage( pInStream );
801         if ( !pInStream->GetError() && !pImp->bIsStorage )
802             bTriedStorage = sal_True;
803     }
804 
805     return pImp->bIsStorage;
806 }
807 
808 //------------------------------------------------------------------
GetDataAvailableLink() const809 Link SfxMedium::GetDataAvailableLink() const
810 {
811     return pImp->aAvailableLink.GetLink();
812 }
813 
814 //------------------------------------------------------------------
GetDoneLink() const815 Link SfxMedium::GetDoneLink() const
816 {
817     return pImp->aDoneLink.GetLink();
818 }
819 
820 //------------------------------------------------------------------
IsPreview_Impl()821 sal_Bool SfxMedium::IsPreview_Impl()
822 {
823     sal_Bool bPreview = sal_False;
824     SFX_ITEMSET_ARG( GetItemSet(), pPreview, SfxBoolItem, SID_PREVIEW, sal_False);
825     if ( pPreview )
826         bPreview = pPreview->GetValue();
827     else
828     {
829         SFX_ITEMSET_ARG( GetItemSet(), pFlags, SfxStringItem, SID_OPTIONS, sal_False);
830         if ( pFlags )
831         {
832             String aFileFlags = pFlags->GetValue();
833             aFileFlags.ToUpperAscii();
834             if ( STRING_NOTFOUND != aFileFlags.Search( 'B' ) )
835                 bPreview = sal_True;
836         }
837     }
838 
839     return bPreview;
840 }
841 
842 //------------------------------------------------------------------
StorageBackup_Impl()843 void SfxMedium::StorageBackup_Impl()
844 {
845 	::ucbhelper::Content aOriginalContent;
846 	Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
847 
848     sal_Bool bBasedOnOriginalFile = ( !pImp->pTempFile && !( aLogicName.Len() && pImp->m_bSalvageMode )
849         && GetURLObject().GetMainURL( INetURLObject::NO_DECODE ).getLength()
850         && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
851         && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
852 
853 	if ( bBasedOnOriginalFile && !pImp->m_aBackupURL.getLength()
854 	  && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aOriginalContent ) )
855 	{
856 		DoInternalBackup_Impl( aOriginalContent );
857 		if( !pImp->m_aBackupURL.getLength() )
858 			SetError( ERRCODE_SFX_CANTCREATEBACKUP, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
859 	}
860 }
861 
862 //------------------------------------------------------------------
GetBackup_Impl()863 ::rtl::OUString SfxMedium::GetBackup_Impl()
864 {
865 	if ( !pImp->m_aBackupURL.getLength() )
866 		StorageBackup_Impl();
867 
868 	return pImp->m_aBackupURL;
869 }
870 
871 //------------------------------------------------------------------
GetOutputStorage()872 uno::Reference < embed::XStorage > SfxMedium::GetOutputStorage()
873 {
874 	if ( GetError() )
875 		return uno::Reference< embed::XStorage >();
876 
877     // if the medium was constructed with a Storage: use this one, not a temp. storage
878     // if a temporary storage already exists: use it
879     if ( pImp->xStorage.is() && ( !aLogicName.Len() || pImp->pTempFile ) )
880         return pImp->xStorage;
881 
882     // if necessary close stream that was used for reading
883     if ( pInStream && !pInStream->IsWritable() )
884         CloseInStream();
885 
886     DBG_ASSERT( !pOutStream, "OutStream in a readonly Medium?!" );
887 
888     // TODO/LATER: The current solution is to store the document temporary and then copy it to the target location;
889     // in future it should be stored directly and then copied to the temporary location, since in this case no
890     // file attributes have to be preserved and system copying mechanics could be used instead of streaming.
891     CreateTempFileNoCopy();
892 
893     return GetStorage();
894 }
895 
896 //------------------------------------------------------------------
SetEncryptionDataToStorage_Impl()897 void SfxMedium::SetEncryptionDataToStorage_Impl()
898 {
899 	// in case media-descriptor contains password it should be used on opening
900 	if ( pImp->xStorage.is() && pSet )
901 	{
902         uno::Sequence< beans::NamedValue > aEncryptionData;
903 		if ( GetEncryptionData_Impl( pSet, aEncryptionData ) )
904 		{
905             // replace the password with encryption data
906             pSet->ClearItem( SID_PASSWORD );
907             pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
908 
909 			try
910 			{
911 				::comphelper::OStorageHelper::SetCommonStorageEncryptionData( pImp->xStorage, aEncryptionData );
912 			}
913 			catch( uno::Exception& )
914 			{
915 				OSL_ENSURE( sal_False, "It must be possible to set a common password for the storage" );
916 				// TODO/LATER: set the error code in case of problem
917 				// SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
918 			}
919 		}
920 	}
921 }
922 
923 //->i126305 -----------------------------------------------------------------
924 //for the time being the aData holds a single OUString, the owner of the lock
ShowLockedWebDAVDocumentDialog(const uno::Sequence<::rtl::OUString> & aData,sal_Bool bIsLoading)925 sal_Int8 SfxMedium::ShowLockedWebDAVDocumentDialog( const uno::Sequence< ::rtl::OUString >& aData, sal_Bool bIsLoading )
926 {
927     sal_Int8 nResult = LOCK_UI_NOLOCK;
928 
929     // show the interaction regarding the document opening
930     uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
931 
932     if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler.is() && bIsLoading )
933     {
934         ::rtl::OUString aDocumentURL = GetURLObject().GetLastName();
935         ::rtl::OUString aInfo;
936         ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl;
937 
938         aInfo = aData[0];
939         if(aData.getLength() > 1 && aData[1].getLength() > 0)
940         {
941             aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\n" ) );
942             aInfo += aData[1];
943         }
944 
945         if ( bIsLoading )
946         {
947             xInteractionRequestImpl = new ::ucbhelper::InteractionRequest(
948                 uno::makeAny( document::LockedDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
949         }
950         else
951         {
952             xInteractionRequestImpl = new ::ucbhelper::InteractionRequest(
953                 uno::makeAny( document::LockedOnSavingRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
954         }
955 
956         uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
957         aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
958         aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
959         aContinuations[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl.get() );
960         xInteractionRequestImpl->setContinuations( aContinuations );
961 
962         xHandler->handle( xInteractionRequestImpl.get() );
963 
964         ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
965         if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
966         {
967             SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
968         }
969         else if ( uno::Reference< task::XInteractionDisapprove >( xSelected.get(), uno::UNO_QUERY ).is() )
970         {
971             // alien lock on loading, user has selected to edit a copy of document
972             // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
973             // means that a copy of the document should be opened
974             GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE, sal_True ) );
975         }
976         else // if ( XSelected == aContinuations[1] )
977         {
978             // alien lock on loading, user has selected to retry saving
979             // TODO/LATER: alien lock on saving, user has selected to retry saving
980             if ( bIsLoading )
981                 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
982             else
983                 nResult = LOCK_UI_TRY;
984         }
985     }
986     else
987     {
988         if ( bIsLoading )
989         {
990             // if no interaction handler is provided the default answer is open readonly
991             // that usually happens in case the document is loaded per API
992             // so the document must be opened readonly for backward compatibility
993             GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
994         }
995         else
996             SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
997     }
998 
999     return nResult;
1000 }
1001 //<-i126305
1002 
1003 //------------------------------------------------------------------
ShowLockedDocumentDialog(const uno::Sequence<::rtl::OUString> & aData,sal_Bool bIsLoading,sal_Bool bOwnLock)1004 sal_Int8 SfxMedium::ShowLockedDocumentDialog( const uno::Sequence< ::rtl::OUString >& aData, sal_Bool bIsLoading, sal_Bool bOwnLock )
1005 {
1006     sal_Int8 nResult = LOCK_UI_NOLOCK;
1007 
1008     // show the interaction regarding the document opening
1009     uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
1010 
1011     if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler.is() && ( bIsLoading || bOwnLock ) )
1012     {
1013         ::rtl::OUString aDocumentURL = GetURLObject().GetLastName();
1014         ::rtl::OUString aInfo;
1015         ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl;
1016 
1017         if ( bOwnLock )
1018         {
1019             if ( aData.getLength() > LOCKFILE_EDITTIME_ID )
1020                 aInfo = aData[LOCKFILE_EDITTIME_ID];
1021 
1022             xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
1023                 document::OwnLockOnDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo, !bIsLoading ) ) );
1024         }
1025         else
1026         {
1027             if ( aData.getLength() > LOCKFILE_EDITTIME_ID )
1028             {
1029                 if ( aData[LOCKFILE_OOOUSERNAME_ID].getLength() )
1030                     aInfo = aData[LOCKFILE_OOOUSERNAME_ID];
1031                 else
1032                     aInfo = aData[LOCKFILE_SYSUSERNAME_ID];
1033 
1034                 if ( aInfo.getLength() && aData[LOCKFILE_EDITTIME_ID].getLength() )
1035                 {
1036                     aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " ( " ) );
1037                     aInfo += aData[LOCKFILE_EDITTIME_ID];
1038                     aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " )" ) );
1039                 }
1040             }
1041 
1042             if ( bIsLoading )
1043             {
1044                 xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
1045                     document::LockedDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
1046             }
1047             else
1048             {
1049                 xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
1050                     document::LockedOnSavingRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
1051 
1052             }
1053         }
1054 
1055         uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
1056         aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
1057         aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
1058         aContinuations[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl.get() );
1059         xInteractionRequestImpl->setContinuations( aContinuations );
1060 
1061         xHandler->handle( xInteractionRequestImpl.get() );
1062 
1063         ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
1064         if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
1065         {
1066             SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1067         }
1068         else if ( uno::Reference< task::XInteractionDisapprove >( xSelected.get(), uno::UNO_QUERY ).is() )
1069         {
1070             // own lock on loading, user has selected to ignore the lock
1071             // own lock on saving, user has selected to ignore the lock
1072             // alien lock on loading, user has selected to edit a copy of document
1073             // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
1074             if ( bIsLoading && !bOwnLock )
1075             {
1076                 // means that a copy of the document should be opened
1077                 GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE, sal_True ) );
1078             }
1079             else if ( bOwnLock )
1080                 nResult = LOCK_UI_SUCCEEDED;
1081         }
1082         else // if ( XSelected == aContinuations[1] )
1083         {
1084             // own lock on loading, user has selected to open readonly
1085             // own lock on saving, user has selected to open readonly
1086             // alien lock on loading, user has selected to retry saving
1087             // TODO/LATER: alien lock on saving, user has selected to retry saving
1088 
1089             if ( bIsLoading )
1090                 GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1091             else
1092                 nResult = LOCK_UI_TRY;
1093         }
1094     }
1095     else
1096     {
1097         if ( bIsLoading )
1098         {
1099             // if no interaction handler is provided the default answer is open readonly
1100             // that usually happens in case the document is loaded per API
1101             // so the document must be opened readonly for backward compatibility
1102             GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1103         }
1104         else
1105             SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1106 
1107     }
1108 
1109     return nResult;
1110 }
1111 
1112 //------------------------------------------------------------------
LockOrigFileOnDemand(sal_Bool bLoading,sal_Bool bNoUI)1113 sal_Bool SfxMedium::LockOrigFileOnDemand( sal_Bool bLoading, sal_Bool bNoUI )
1114 {
1115     // returns true if the document can be opened for editing ( even if it should be a copy )
1116     // otherwise the document should be opened readonly
1117     // if user cancel the loading the ERROR_ABORT is set
1118 
1119     if ( pImp->m_bLocked && bLoading && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
1120     {
1121         // if the document is already locked the system locking might be temporarely off after storing
1122         // check whether the system file locking should be taken again
1123         GetLockingStream_Impl();
1124     }
1125 
1126     sal_Bool bResult = pImp->m_bLocked;
1127 
1128     if ( !bResult )
1129     {
1130         // no read-write access is necessary on loading if the document is explicitly opened as copy
1131         SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem, SfxBoolItem, SID_TEMPLATE, sal_False);
1132         bResult = ( bLoading && pTemplateItem && pTemplateItem->GetValue() );
1133     }
1134 
1135     if ( !bResult && !IsReadOnly() )
1136     {
1137         sal_Bool bContentReadonly = sal_False;
1138         if ( bLoading && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
1139         {
1140             // let the original document be opened to check the possibility to open it for editing
1141             // and to let the writable stream stay open to hold the lock on the document
1142             GetLockingStream_Impl();
1143         }
1144 
1145         // "IsReadOnly" property does not allow to detect whether the file is readonly always
1146         // so we try always to open the file for editing
1147         // the file is readonly only in case the read-write stream can not be opened
1148         if ( bLoading && !pImp->m_xLockingStream.is() )
1149         {
1150             try
1151             {
1152                 // MediaDescriptor does this check also, the duplication should be avoided in future
1153                 Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
1154                 ::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv );
1155                 aContent.getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) ) >>= bContentReadonly;
1156             }
1157             catch( uno::Exception )
1158             {}
1159 
1160             if ( !bContentReadonly )
1161             {
1162                 // the file is not readonly, check the ACL
1163 
1164                 String aPhysPath;
1165                 if ( ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aPhysPath ) )
1166                     bContentReadonly = IsReadonlyAccordingACL( aPhysPath.GetBuffer() );
1167             }
1168         }
1169 
1170         // do further checks only if the file not readonly in fs
1171         if ( !bContentReadonly )
1172         {
1173             // the special file locking should be used only for file URLs
1174             if ( ::utl::LocalFileHelper::IsLocalFile( aLogicName ) )
1175             {
1176 
1177                 // in case of storing the document should request the output before locking
1178                 if ( bLoading )
1179                 {
1180                     // let the stream be opened to check the system file locking
1181                     GetMedium_Impl();
1182                 }
1183 
1184                 sal_Int8 bUIStatus = LOCK_UI_NOLOCK;
1185 
1186                 // check whether system file locking has been used, the default value is false
1187                 sal_Bool bUseSystemLock = IsSystemFileLockingUsed();
1188 
1189                 // TODO/LATER: This implementation does not allow to detect the system lock on saving here, actually this is no big problem
1190                 // if system lock is used the writeable stream should be available
1191                 sal_Bool bHandleSysLocked = ( bLoading && bUseSystemLock && !pImp->xStream.is() && !pOutStream );
1192 
1193                 do
1194                 {
1195                     try
1196                     {
1197                         ::svt::DocumentLockFile aLockFile( aLogicName );
1198                         if ( !bHandleSysLocked )
1199                         {
1200                             try
1201                             {
1202                                 bResult = aLockFile.CreateOwnLockFile();
1203                             }
1204                             catch ( ucb::InteractiveIOException& e )
1205                             {
1206                                 // exception means that the lock file can not be successfully accessed
1207                                 // in this case it should be ignored if system file locking is anyway active
1208                                 if ( bUseSystemLock || !IsOOoLockFileUsed() )
1209                                 {
1210                                     bResult = sal_True;
1211                                     // take the ownership over the lock file
1212                                     aLockFile.OverwriteOwnLockFile();
1213                                 }
1214                                 else if ( e.Code == IOErrorCode_INVALID_PARAMETER )
1215                                 {
1216                                     // system file locking is not active, ask user whether he wants to open the document without any locking
1217                                     uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
1218 
1219                                     if ( xHandler.is() )
1220                                     {
1221                                         ::rtl::Reference< ::ucbhelper::InteractionRequest > xIgnoreRequestImpl
1222                                             = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
1223 
1224                                         uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 2 );
1225                                         aContinuations[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl.get() );
1226                                         aContinuations[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl.get() );
1227                                         xIgnoreRequestImpl->setContinuations( aContinuations );
1228 
1229                                         xHandler->handle( xIgnoreRequestImpl.get() );
1230 
1231                                         ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xIgnoreRequestImpl->getSelection();
1232                                         bResult = (  uno::Reference< task::XInteractionApprove >( xSelected.get(), uno::UNO_QUERY ).is() );
1233                                     }
1234                                 }
1235                             }
1236                             catch ( uno::Exception& )
1237                             {
1238                                 // exception means that the lock file can not be successfully accessed
1239                                 // in this case it should be ignored if system file locking is anyway active
1240                                 if ( bUseSystemLock || !IsOOoLockFileUsed() )
1241                                 {
1242                                     bResult = sal_True;
1243                                     // take the ownership over the lock file
1244                                     aLockFile.OverwriteOwnLockFile();
1245                                 }
1246                             }
1247 
1248                             // in case OOo locking is turned off the lock file is still written if possible
1249                             // but it is ignored while deciding whether the document should be opened for editing or not
1250                             if ( !bResult && !IsOOoLockFileUsed() )
1251                             {
1252                                 bResult = sal_True;
1253                                 // take the ownership over the lock file
1254                                 aLockFile.OverwriteOwnLockFile();
1255                             }
1256                         }
1257 
1258 
1259                         if ( !bResult )
1260                         {
1261                             uno::Sequence< ::rtl::OUString > aData;
1262                             try
1263                             {
1264                                 // impossibility to get data is no real problem
1265                                 aData = aLockFile.GetLockData();
1266                             }
1267                             catch( uno::Exception ) {}
1268 
1269                             sal_Bool bOwnLock = sal_False;
1270 
1271                             if ( !bHandleSysLocked )
1272                             {
1273                                 uno::Sequence< ::rtl::OUString > aOwnData = aLockFile.GenerateOwnEntry();
1274                                 bOwnLock = ( aData.getLength() > LOCKFILE_USERURL_ID
1275                                           && aOwnData.getLength() > LOCKFILE_USERURL_ID
1276                                           && aOwnData[LOCKFILE_SYSUSERNAME_ID].equals( aData[LOCKFILE_SYSUSERNAME_ID] ) );
1277 
1278                                 if ( bOwnLock
1279                                   && aOwnData[LOCKFILE_LOCALHOST_ID].equals( aData[LOCKFILE_LOCALHOST_ID] )
1280                                   && aOwnData[LOCKFILE_USERURL_ID].equals( aData[LOCKFILE_USERURL_ID] ) )
1281                                 {
1282                                     // this is own lock from the same installation, it could remain because of crash
1283                                     bResult = sal_True;
1284                                 }
1285                             }
1286 
1287                             if ( !bResult && !bNoUI )
1288                             {
1289                                 bUIStatus = ShowLockedDocumentDialog( aData, bLoading, bOwnLock );
1290                                 if ( bUIStatus == LOCK_UI_SUCCEEDED )
1291                                 {
1292                                     // take the ownership over the lock file
1293                                     bResult = aLockFile.OverwriteOwnLockFile();
1294                                 }
1295                             }
1296 
1297                             bHandleSysLocked = sal_False;
1298                         }
1299                     }
1300                     catch( uno::Exception& )
1301                     {
1302                     }
1303                 } while( !bResult && bUIStatus == LOCK_UI_TRY );
1304 
1305                 pImp->m_bLocked = bResult;
1306             }
1307             else
1308             {
1309                 //->i126305
1310                 // check if path scheme is http:// or https://
1311                 ::rtl::OUString aScheme =  INetURLObject::GetScheme(GetURLObject().GetProtocol());
1312                 if( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) ||
1313                     aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) )
1314                 {
1315                     //so, this is webdav stuff...
1316                     Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
1317                     if ( !bResult )
1318                     {
1319                         // no read-write access is necessary on loading if the document is explicitly opened as copy
1320                         SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem, SfxBoolItem, SID_TEMPLATE, sal_False);
1321                         bResult = ( bLoading && pTemplateItem && pTemplateItem->GetValue() );
1322                     }
1323 
1324                     if ( !bResult && !IsReadOnly() )
1325                     {
1326 
1327                         // in case of storing the document should request the output before locking
1328                         if ( bLoading )
1329                         {
1330                             // let the stream be opened to check the system file locking
1331                             GetMedium_Impl();
1332                         }
1333 
1334                         sal_Int8 bUIStatus = LOCK_UI_NOLOCK;
1335                         do
1336                         {
1337                             if( !bResult )
1338                             {
1339                                 Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
1340                                 uno::Reference< task::XInteractionHandler > xCHandler = GetAuthenticationInteractionHandler();
1341                                 xComEnv = new ::ucbhelper::CommandEnvironment( xCHandler,
1342                                                                                Reference< ::com::sun::star::ucb::XProgressHandler >() );
1343                                 ::ucbhelper::Content aContentToLock( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xComEnv);
1344                                 rtl::OUString   aOwner;
1345                                 try {
1346                                     aContentToLock.lock();
1347                                     bResult = sal_True;
1348                                 }
1349                                 catch( ucb::InteractiveLockingLockNotAvailableException )
1350                                 {
1351                                     // signalled when the lock can not be done because the method is known but not allowed on the resource
1352                                     // the resource is still available, can be worked upon, at your risk
1353                                     // so ask user whether he wants to open the document without any locking
1354                                     uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
1355 
1356                                     if ( xHandler.is() )
1357                                     {
1358                                         ::rtl::Reference< ::ucbhelper::InteractionRequest > xIgnoreRequestImpl
1359                                             = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
1360 
1361                                         uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 2 );
1362                                         aContinuations[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl.get() );
1363                                         aContinuations[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl.get() );
1364                                         xIgnoreRequestImpl->setContinuations( aContinuations );
1365 
1366                                         xHandler->handle( xIgnoreRequestImpl.get() );
1367 
1368                                         ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xIgnoreRequestImpl->getSelection();
1369                                         bResult = (  uno::Reference< task::XInteractionApprove >( xSelected.get(), uno::UNO_QUERY ).is() );
1370                                     }
1371                                 }
1372                                 catch( ucb::InteractiveLockingLockedException& e )
1373                                 {
1374                                     // here get the lock owner currently active
1375                                     aOwner = e.Owner;
1376                                     rtl::OUString aExtendedError;
1377 
1378                                     if ( !bResult && !bNoUI )
1379                                     {
1380                                         uno::Sequence< ::rtl::OUString > aData( 2 );
1381 
1382                                         aData[0] = aOwner;
1383                                         aData[1] = aExtendedError;
1384                                         bUIStatus = ShowLockedWebDAVDocumentDialog( aData, bLoading );
1385                                         if ( bUIStatus == LOCK_UI_SUCCEEDED )
1386                                         {
1387                                             // take the ownership over the lock file, accept the current lock (already there)
1388                                             bResult = sal_True;
1389                                         }
1390                                     }
1391                                 }
1392                             }
1393                         } while( !bResult && bUIStatus == LOCK_UI_TRY );
1394                     }
1395 
1396                     if ( !bResult && GetError() == ERRCODE_NONE )
1397                     {
1398                         // the error should be set in case it is storing process
1399                         // or the document has been opened for editing explicitly
1400                         SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
1401                         if ( !bLoading || (pReadOnlyItem && !pReadOnlyItem->GetValue()) )
1402                             SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1403                         else
1404                             GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1405                     }
1406 
1407                     pImp->m_bLocked = bResult;
1408                 }
1409                 else
1410                 {
1411                     // this is neither file URL nor WebDAV, check whether the file is readonly
1412                     bResult = !bContentReadonly;
1413                 }
1414                 //<-i126305
1415             }
1416         }
1417     }
1418 
1419     if ( !bResult && GetError() == ERRCODE_NONE )
1420     {
1421         // the error should be set in case it is storing process
1422         // or the document has been opened for editing explicitly
1423 
1424         SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
1425         if ( !bLoading || (pReadOnlyItem && !pReadOnlyItem->GetValue()) )
1426             SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1427         else
1428             GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1429     }
1430 
1431     // when the file is locked, get the current file date
1432     if ( bResult && DocNeedsFileDateCheck() )
1433         GetInitFileDate( sal_True );
1434 
1435     return bResult;
1436 }
1437 
1438 //------------------------------------------------------------------
GetStorage(sal_Bool bCreateTempIfNo)1439 uno::Reference < embed::XStorage > SfxMedium::GetStorage( sal_Bool bCreateTempIfNo )
1440 {
1441     if ( pImp->xStorage.is() || bTriedStorage )
1442         return pImp->xStorage;
1443 
1444     uno::Sequence< uno::Any > aArgs( 2 );
1445 
1446     // the medium should be retrieved before temporary file creation
1447     // to let the MediaDescriptor be filled with the streams
1448     GetMedium_Impl();
1449 
1450     if ( bCreateTempIfNo )
1451         CreateTempFile( sal_False );
1452 
1453     GetMedium_Impl();
1454 
1455     if ( GetError() )
1456         return pImp->xStorage;
1457 
1458     SFX_ITEMSET_ARG( GetItemSet(), pRepairItem, SfxBoolItem, SID_REPAIRPACKAGE, sal_False);
1459     if ( pRepairItem && pRepairItem->GetValue() )
1460     {
1461         // the storage should be created for repairing mode
1462         CreateTempFile( sal_False );
1463         GetMedium_Impl();
1464 
1465         Reference< ::com::sun::star::ucb::XProgressHandler > xProgressHandler;
1466         Reference< ::com::sun::star::task::XStatusIndicator > xStatusIndicator;
1467 
1468         SFX_ITEMSET_ARG( GetItemSet(), pxProgressItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, sal_False );
1469         if( pxProgressItem && ( pxProgressItem->GetValue() >>= xStatusIndicator ) )
1470             xProgressHandler = Reference< ::com::sun::star::ucb::XProgressHandler >(
1471                                     new utl::ProgressHandlerWrap( xStatusIndicator ) );
1472 
1473         uno::Sequence< beans::PropertyValue > aAddProps( 2 );
1474         aAddProps[0].Name = ::rtl::OUString::createFromAscii( "RepairPackage" );
1475         aAddProps[0].Value <<= (sal_Bool)sal_True;
1476         aAddProps[1].Name = ::rtl::OUString::createFromAscii( "StatusIndicator" );
1477         aAddProps[1].Value <<= xProgressHandler;
1478 
1479         // the first arguments will be filled later
1480         aArgs.realloc( 3 );
1481         aArgs[2] <<= aAddProps;
1482     }
1483 
1484     if ( pImp->xStream.is() )
1485     {
1486         // since the storage is based on temporary stream we open it always read-write
1487         aArgs[0] <<= pImp->xStream;
1488         aArgs[1] <<= embed::ElementModes::READWRITE;
1489         pImp->bStorageBasedOnInStream = sal_True;
1490     }
1491     else if ( pImp->xInputStream.is() )
1492     {
1493         // since the storage is based on temporary stream we open it always read-write
1494         aArgs[0] <<= pImp->xInputStream;
1495         aArgs[1] <<= embed::ElementModes::READ;
1496         pImp->bStorageBasedOnInStream = sal_True;
1497     }
1498     else
1499     {
1500         CloseStreams_Impl();
1501         aArgs[0] <<= ::rtl::OUString( aName );
1502         aArgs[1] <<= embed::ElementModes::READ;
1503         pImp->bStorageBasedOnInStream = sal_False;
1504     }
1505 
1506     try
1507     {
1508         pImp->xStorage = uno::Reference< embed::XStorage >(
1509                             ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs ),
1510                             uno::UNO_QUERY );
1511     }
1512     catch( uno::Exception& )
1513     {
1514         // impossibility to create the storage is no error
1515     }
1516 
1517     if( ( pImp->nLastStorageError = GetError() ) != SVSTREAM_OK )
1518     {
1519         pImp->xStorage = 0;
1520         if ( pInStream )
1521             pInStream->Seek(0);
1522         return uno::Reference< embed::XStorage >();
1523     }
1524 
1525     bTriedStorage = sal_True;
1526 
1527     // TODO/LATER: Get versionlist on demand
1528     if ( pImp->xStorage.is() )
1529 	{
1530         SetEncryptionDataToStorage_Impl();
1531         GetVersionList();
1532 	}
1533 
1534     SFX_ITEMSET_ARG( pSet, pVersion, SfxInt16Item, SID_VERSION, sal_False);
1535 
1536     sal_Bool bResetStorage = sal_False;
1537     if ( pVersion && pVersion->GetValue() )
1538     {
1539         // Alle verf"ugbaren Versionen einlesen
1540         if ( pImp->aVersions.getLength() )
1541         {
1542             // Die zum Kommentar passende Version suchen
1543             // Die Versionen sind von 1 an durchnumeriert, mit negativen
1544             // Versionsnummern werden die Versionen von der aktuellen aus
1545             // r"uckw"arts gez"ahlt
1546             short nVersion = pVersion ? pVersion->GetValue() : 0;
1547             if ( nVersion<0 )
1548                 nVersion = ( (short) pImp->aVersions.getLength() ) + nVersion;
1549             else if ( nVersion )
1550                 nVersion--;
1551 
1552             util::RevisionTag& rTag = pImp->aVersions[nVersion];
1553             {
1554                 // SubStorage f"ur alle Versionen "offnen
1555                 uno::Reference < embed::XStorage > xSub = pImp->xStorage->openStorageElement( DEFINE_CONST_UNICODE( "Versions" ),
1556                         embed::ElementModes::READ );
1557 
1558                 DBG_ASSERT( xSub.is(), "Versionsliste, aber keine Versionen!" );
1559 
1560                 // Dort ist die Version als gepackter Stream gespeichert
1561                 uno::Reference < io::XStream > xStr = xSub->openStreamElement( rTag.Identifier, embed::ElementModes::READ );
1562                 SvStream* pStream = utl::UcbStreamHelper::CreateStream( xStr );
1563                 if ( pStream && pStream->GetError() == SVSTREAM_OK )
1564                 {
1565                     // Stream ins TempDir auspacken
1566                     ::utl::TempFile aTempFile;
1567                     String          aTmpName = aTempFile.GetURL();
1568                     SvFileStream    aTmpStream( aTmpName, SFX_STREAM_READWRITE );
1569 
1570                     *pStream >> aTmpStream;
1571                     aTmpStream.Close();
1572 
1573                     // Datei als Storage "offnen
1574                     nStorOpenMode = SFX_STREAM_READONLY;
1575                     pImp->xStorage = comphelper::OStorageHelper::GetStorageFromURL( aTmpName, embed::ElementModes::READ );
1576                     pImp->bStorageBasedOnInStream = sal_False;
1577                     String aTemp;
1578                     ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName, aTemp );
1579                     SetPhysicalName_Impl( aTemp );
1580 
1581                     pImp->bIsTemp = sal_True;
1582                     GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
1583                     // TODO/MBA
1584                     pImp->aVersions.realloc(0);
1585                 }
1586                 else
1587                     bResetStorage = sal_True;
1588             }
1589         }
1590         else
1591             bResetStorage = sal_True;
1592     }
1593 
1594     if ( bResetStorage )
1595     {
1596         pImp->xStorage = 0;
1597         if ( pInStream )
1598             pInStream->Seek( 0L );
1599     }
1600 
1601     pImp->bIsStorage = pImp->xStorage.is();
1602     return pImp->xStorage;
1603 }
1604 
1605 //------------------------------------------------------------------
GetZipStorageToSign_Impl(sal_Bool bReadOnly)1606 uno::Reference< embed::XStorage > SfxMedium::GetZipStorageToSign_Impl( sal_Bool bReadOnly )
1607 {
1608     if ( !GetError() && !pImp->m_xZipStorage.is() )
1609     {
1610         // very careful!!!
1611         // if bReadOnly == sal_False and there is no temporary file the original file might be used
1612         GetMedium_Impl();
1613 
1614         try
1615         {
1616             // we can not sign document if there is no stream
1617             // should it be possible at all?
1618             if ( !bReadOnly && pImp->xStream.is() )
1619             {
1620                 pImp->m_xZipStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING, pImp->xStream, embed::ElementModes::READWRITE );
1621             }
1622             else if ( pImp->xInputStream.is() )
1623             {
1624                 pImp->m_xZipStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( ZIP_STORAGE_FORMAT_STRING, pImp->xInputStream );
1625             }
1626         }
1627         catch( uno::Exception& )
1628         {
1629             OSL_ENSURE( sal_False, "No possibility to get readonly version of storage from medium!\n" );
1630         }
1631 
1632         if ( GetError() ) // do not remove warnings
1633             ResetError();
1634     }
1635 
1636     return pImp->m_xZipStorage;
1637 }
1638 
1639 //------------------------------------------------------------------
CloseZipStorage_Impl()1640 void SfxMedium::CloseZipStorage_Impl()
1641 {
1642 	if ( pImp->m_xZipStorage.is() )
1643 	{
1644 		try {
1645 			pImp->m_xZipStorage->dispose();
1646 		} catch( uno::Exception& )
1647 		{}
1648 
1649 		pImp->m_xZipStorage = uno::Reference< embed::XStorage >();
1650 	}
1651 }
1652 
1653 //------------------------------------------------------------------
CloseStorage()1654 void SfxMedium::CloseStorage()
1655 {
1656     if ( pImp->xStorage.is() )
1657     {
1658         uno::Reference < lang::XComponent > xComp( pImp->xStorage, uno::UNO_QUERY );
1659 		// in the salvage mode the medium does not own the storage
1660         if ( pImp->bDisposeStorage && !pImp->m_bSalvageMode )
1661 		{
1662 			try {
1663             	xComp->dispose();
1664 			} catch( uno::Exception& )
1665 			{
1666 				OSL_ENSURE( sal_False, "Medium's storage is already disposed!\n" );
1667 			}
1668 		}
1669 
1670         pImp->xStorage = 0;
1671     	pImp->bStorageBasedOnInStream = sal_False;
1672     }
1673 
1674     bTriedStorage = sal_False;
1675     pImp->bIsStorage = sal_False;
1676 }
1677 
CanDisposeStorage_Impl(sal_Bool bDisposeStorage)1678 void SfxMedium::CanDisposeStorage_Impl( sal_Bool bDisposeStorage )
1679 {
1680     pImp->bDisposeStorage = bDisposeStorage;
1681 }
1682 
WillDisposeStorageOnClose_Impl()1683 sal_Bool SfxMedium::WillDisposeStorageOnClose_Impl()
1684 {
1685 	return pImp->bDisposeStorage;
1686 }
1687 
1688 //------------------------------------------------------------------
SetOpenMode(StreamMode nStorOpen,sal_Bool bDirectP,sal_Bool bDontClose)1689 void SfxMedium::SetOpenMode( StreamMode nStorOpen,
1690                              sal_Bool bDirectP,
1691                              sal_Bool bDontClose )
1692 {
1693     if ( nStorOpenMode != nStorOpen )
1694     {
1695         nStorOpenMode = nStorOpen;
1696 
1697         if( !bDontClose )
1698         {
1699             if ( pImp->xStorage.is() )
1700                 CloseStorage();
1701 
1702             CloseStreams_Impl();
1703         }
1704     }
1705 
1706     bDirect     = bDirectP;
1707     bSetFilter  = sal_False;
1708 }
1709 
1710 //------------------------------------------------------------------
UseBackupToRestore_Impl(::ucbhelper::Content & aOriginalContent,const Reference<::com::sun::star::ucb::XCommandEnvironment> & xComEnv)1711 sal_Bool SfxMedium::UseBackupToRestore_Impl( ::ucbhelper::Content& aOriginalContent,
1712 											const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
1713 {
1714 	try
1715 	{
1716 		::ucbhelper::Content aTransactCont( pImp->m_aBackupURL, xComEnv );
1717 
1718 		Reference< XInputStream > aOrigInput = aTransactCont.openStream();
1719 		aOriginalContent.writeStream( aOrigInput, sal_True );
1720 		return sal_True;
1721 	}
1722 	catch( Exception& )
1723 	{
1724 		// in case of failure here the backup file should not be removed
1725 		// TODO/LATER: a message should be used to let user know about the backup
1726 		pImp->m_bRemoveBackup = sal_False;
1727 		// TODO/LATER: needs a specific error code
1728 		eError = ERRCODE_IO_GENERAL;
1729 	}
1730 
1731 	return sal_False;
1732 }
1733 
1734 //------------------------------------------------------------------
StorageCommit_Impl()1735 sal_Bool SfxMedium::StorageCommit_Impl()
1736 {
1737 	sal_Bool bResult = sal_False;
1738 	Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
1739 	::ucbhelper::Content aOriginalContent;
1740 
1741 	if ( pImp->xStorage.is() )
1742 	{
1743 		if ( !GetError() )
1744 		{
1745         	uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
1746         	if ( xTrans.is() )
1747         	{
1748             	try
1749             	{
1750                 	xTrans->commit();
1751 					CloseZipStorage_Impl();
1752 					bResult = sal_True;
1753             	}
1754 				catch ( embed::UseBackupException& aBackupExc )
1755 				{
1756                     // since the temporary file is created always now, the scenario is close to be impossible
1757 					if ( !pImp->pTempFile )
1758 					{
1759 						OSL_ENSURE( pImp->m_aBackupURL.getLength(), "No backup on storage commit!\n" );
1760 						if ( pImp->m_aBackupURL.getLength()
1761 							&& ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
1762 														xDummyEnv,
1763 														aOriginalContent ) )
1764 						{
1765 							// use backup to restore the file
1766 							// the storage has already disconnected from original location
1767 							CloseAndReleaseStreams_Impl();
1768 							if ( !UseBackupToRestore_Impl( aOriginalContent, xDummyEnv ) )
1769 							{
1770 								// connect the medium to the temporary file of the storage
1771             					pImp->aContent = ::ucbhelper::Content();
1772         						aName = aBackupExc.TemporaryFileURL;
1773 								OSL_ENSURE( aName.Len(), "The exception _must_ contain the temporary URL!\n" );
1774 							}
1775 						}
1776 
1777 						if ( !GetError() )
1778         					SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1779 					}
1780 				}
1781             	catch ( uno::Exception& )
1782             	{
1783                 	//TODO/LATER: improve error handling
1784         			SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
1785             	}
1786         	}
1787 		}
1788 	}
1789 
1790 	return bResult;
1791 }
1792 
1793 //------------------------------------------------------------------
TransactedTransferForFS_Impl(const INetURLObject & aSource,const INetURLObject & aDest,const Reference<::com::sun::star::ucb::XCommandEnvironment> & xComEnv)1794 sal_Bool SfxMedium::TransactedTransferForFS_Impl( const INetURLObject& aSource,
1795 											 	const INetURLObject& aDest,
1796 											 	const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
1797 {
1798 	sal_Bool bResult = sal_False;
1799 	Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
1800 	Reference< XOutputStream > aDestStream;
1801 	::ucbhelper::Content aOriginalContent;
1802 
1803     try
1804     {
1805         aOriginalContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
1806     }
1807     catch ( ::com::sun::star::ucb::CommandAbortedException& )
1808     {
1809         eError = ERRCODE_ABORT;
1810     }
1811     catch ( ::com::sun::star::ucb::CommandFailedException& )
1812     {
1813         eError = ERRCODE_ABORT;
1814     }
1815     catch (const ::com::sun::star::ucb::ContentCreationException& ex)
1816     {
1817         eError = ERRCODE_IO_GENERAL;
1818         if (
1819             (ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER    ) ||
1820             (ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
1821            )
1822         {
1823             eError = ERRCODE_IO_NOTEXISTSPATH;
1824         }
1825     }
1826     catch (const ::com::sun::star::uno::Exception&)
1827     {
1828        eError = ERRCODE_IO_GENERAL;
1829     }
1830 
1831     if( !eError || (eError & ERRCODE_WARNING_MASK) )
1832 	{
1833         if ( pImp->xStorage.is() )
1834             CloseStorage();
1835 
1836         CloseStreams_Impl();
1837 
1838 		::ucbhelper::Content aTempCont;
1839 		if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aTempCont ) )
1840 		{
1841 			sal_Bool bTransactStarted = sal_False;
1842 			SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
1843    			SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
1844 			sal_Bool bRename = pRename ? pRename->GetValue() : sal_False;
1845 			sal_Bool bOverWrite = pOverWrite ? pOverWrite->GetValue() : !bRename;
1846 
1847 			try
1848 			{
1849 				if( bOverWrite && ::utl::UCBContentHelper::IsDocument( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) )
1850 				{
1851 					if( ! pImp->m_aBackupURL.getLength() )
1852 						DoInternalBackup_Impl( aOriginalContent );
1853 
1854 					if( pImp->m_aBackupURL.getLength() )
1855 					{
1856 						Reference< XInputStream > aTempInput = aTempCont.openStream();
1857 						bTransactStarted = sal_True;
1858 						aOriginalContent.setPropertyValue( ::rtl::OUString::createFromAscii( "Size" ),
1859 															uno::makeAny( (sal_Int64)0 ) );
1860 						aOriginalContent.writeStream( aTempInput, bOverWrite );
1861 						bResult = sal_True;
1862 					}
1863 					else
1864 					{
1865 						eError = ERRCODE_SFX_CANTCREATEBACKUP;
1866 					}
1867 				}
1868 				else
1869 				{
1870 					Reference< XInputStream > aTempInput = aTempCont.openStream();
1871 					aOriginalContent.writeStream( aTempInput, bOverWrite );
1872 					bResult = sal_True;
1873 				}
1874 			}
1875 			catch ( ::com::sun::star::ucb::CommandAbortedException& )
1876 			{
1877 				eError = ERRCODE_ABORT;
1878 			}
1879 			catch ( ::com::sun::star::ucb::CommandFailedException& )
1880 			{
1881 				eError = ERRCODE_ABORT;
1882 			}
1883 			catch ( ::com::sun::star::ucb::InteractiveIOException& r )
1884 			{
1885 				if ( r.Code == IOErrorCode_ACCESS_DENIED )
1886 					eError = ERRCODE_IO_ACCESSDENIED;
1887 				else if ( r.Code == IOErrorCode_NOT_EXISTING )
1888 					eError = ERRCODE_IO_NOTEXISTS;
1889 				else if ( r.Code == IOErrorCode_CANT_READ )
1890 					eError = ERRCODE_IO_CANTREAD;
1891 				else
1892 					eError = ERRCODE_IO_GENERAL;
1893 			}
1894             catch ( ::com::sun::star::uno::Exception& )
1895 			{
1896 				eError = ERRCODE_IO_GENERAL;
1897 			}
1898 
1899    			if ( bResult )
1900    			{
1901 				if ( pImp->pTempFile )
1902 				{
1903 					pImp->pTempFile->EnableKillingFile( sal_True );
1904    					delete pImp->pTempFile;
1905    					pImp->pTempFile = NULL;
1906 				}
1907    			}
1908 			else if ( bTransactStarted )
1909 			{
1910 				UseBackupToRestore_Impl( aOriginalContent, xDummyEnv );
1911 			}
1912 		}
1913 		else
1914 			eError = ERRCODE_IO_CANTREAD;
1915 	}
1916 
1917 	return bResult;
1918 }
1919 
1920 //------------------------------------------------------------------
TryDirectTransfer(const::rtl::OUString & aURL,SfxItemSet & aTargetSet)1921 sal_Bool SfxMedium::TryDirectTransfer( const ::rtl::OUString& aURL, SfxItemSet& aTargetSet )
1922 {
1923     if ( GetError() )
1924         return sal_False;
1925 
1926 	// if the document had no password it should be stored without password
1927 	// if the document had password it should be stored with the same password
1928 	// otherwise the stream copying can not be done
1929     SFX_ITEMSET_ARG( &aTargetSet, pNewPassItem, SfxStringItem, SID_PASSWORD, sal_False );
1930     SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem, SfxStringItem, SID_PASSWORD, sal_False );
1931 	if ( ( !pNewPassItem && !pOldPassItem )
1932 	  || ( pNewPassItem && pOldPassItem && pNewPassItem->GetValue().Equals( pOldPassItem->GetValue() ) ) )
1933 	{
1934 		// the filter must be the same
1935 		SFX_ITEMSET_ARG( &aTargetSet, pNewFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
1936     	SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
1937 		if ( pNewFilterItem && pOldFilterItem && pNewFilterItem->GetValue().Equals( pOldFilterItem->GetValue() ) )
1938 		{
1939 			// get the input stream and copy it
1940 			// in case of success return true
1941 			uno::Reference< io::XInputStream > xInStream = GetInputStream();
1942 
1943             ResetError();
1944 			if ( xInStream.is() )
1945 			{
1946 				try
1947 				{
1948 					uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
1949 					sal_Int64 nPos = 0;
1950 					if ( xSeek.is() )
1951 					{
1952 						nPos = xSeek->getPosition();
1953 						xSeek->seek( 0 );
1954 					}
1955 
1956         			uno::Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
1957 					::ucbhelper::Content aTargetContent( aURL, xEnv );
1958 
1959             		InsertCommandArgument aInsertArg;
1960             		aInsertArg.Data = xInStream;
1961                		SFX_ITEMSET_ARG( &aTargetSet, pRename, SfxBoolItem, SID_RENAME, sal_False );
1962                		SFX_ITEMSET_ARG( &aTargetSet, pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
1963                		if ( (pOverWrite && !pOverWrite->GetValue()) // argument says: never overwrite
1964                		  || (pRename && pRename->GetValue()) ) // argument says: rename file
1965             			aInsertArg.ReplaceExisting = sal_False;
1966                		else
1967             			aInsertArg.ReplaceExisting = sal_True; // default is overwrite existing files
1968 
1969     				Any aCmdArg;
1970             		aCmdArg <<= aInsertArg;
1971 					aTargetContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
1972 													aCmdArg );
1973 
1974 					if ( xSeek.is() )
1975 						xSeek->seek( nPos );
1976 
1977 					return sal_True;
1978 				}
1979 				catch( uno::Exception& )
1980 				{}
1981 			}
1982 		}
1983 	}
1984 
1985 	return sal_False;
1986 }
1987 
1988 //------------------------------------------------------------------
Transfer_Impl()1989 void SfxMedium::Transfer_Impl()
1990 {
1991 	// The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
1992 	String aNameURL;
1993 	if ( pImp->pTempFile )
1994 		aNameURL = pImp->pTempFile->GetURL();
1995 	else if ( aLogicName.Len() && pImp->m_bSalvageMode )
1996 	{
1997 		// makes sense only in case logic name is set
1998 		if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aNameURL ) )
1999 			OSL_ENSURE( sal_False, "The medium name is not convertable!\n" );
2000 	}
2001 
2002     if ( aNameURL.Len() && ( !eError || (eError & ERRCODE_WARNING_MASK) ) )
2003     {
2004 		RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::Transfer_Impl, copying to target" );
2005 
2006         Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
2007 		Reference< XOutputStream > rOutStream;
2008 
2009 		// in case an output stream is provided from outside and the URL is correct
2010 		// commit to the stream
2011         if( aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL )
2012 		{
2013 			// TODO/LATER: support storing to SID_STREAM
2014 	   		SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
2015 	 		if( pOutStreamItem && ( pOutStreamItem->GetValue() >>= rOutStream ) )
2016 			{
2017                 if ( pImp->xStorage.is() )
2018                     CloseStorage();
2019 
2020                 CloseStreams_Impl();
2021 
2022     		    INetURLObject aSource( aNameURL );
2023 				::ucbhelper::Content aTempCont;
2024 				if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aTempCont ) )
2025 				{
2026 					try
2027 					{
2028 						sal_Int32 nRead;
2029 						sal_Int32 nBufferSize = 32767;
2030 						Sequence < sal_Int8 > aSequence ( nBufferSize );
2031 						Reference< XInputStream > aTempInput = aTempCont.openStream();
2032 
2033 						do
2034 						{
2035 							nRead = aTempInput->readBytes ( aSequence, nBufferSize );
2036 							if ( nRead < nBufferSize )
2037 							{
2038 								Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
2039 								rOutStream->writeBytes ( aTempBuf );
2040 							}
2041 							else
2042 								rOutStream->writeBytes ( aSequence );
2043 						}
2044 						while ( nRead == nBufferSize );
2045 
2046 						// remove temporary file
2047 						if ( pImp->pTempFile )
2048 						{
2049             				pImp->pTempFile->EnableKillingFile( sal_True );
2050             				delete pImp->pTempFile;
2051             				pImp->pTempFile = NULL;
2052 						}
2053 					}
2054 					catch( Exception& )
2055 					{}
2056 				}
2057        		}
2058 			else
2059 			{
2060 				DBG_ERROR( "Illegal Output stream parameter!\n" );
2061         		SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
2062 			}
2063 
2064 			// free the reference
2065     		if ( pSet )
2066 				pSet->ClearItem( SID_OUTPUTSTREAM );
2067 
2068 			return;
2069 		}
2070 
2071         GetContent();
2072         if ( !pImp->aContent.get().is() )
2073         {
2074             eError = ERRCODE_IO_NOTEXISTS;
2075             return;
2076         }
2077 
2078         SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize, SfxInt32Item, SID_SEGMENTSIZE, sal_False);
2079         if ( pSegmentSize )
2080         {
2081             // this file must be stored into a disk spanned package
2082             try
2083             {
2084                 uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetStorageFromURL( GetName(),
2085                         embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
2086 
2087                 // set segment size property; package will automatically be divided in pieces fitting
2088                 // into this size
2089                 ::com::sun::star::uno::Any aAny;
2090                 aAny <<= pSegmentSize->GetValue();
2091 
2092                 uno::Reference < beans::XPropertySet > xSet( pImp->xStorage, uno::UNO_QUERY );
2093                 xSet->setPropertyValue( String::CreateFromAscii("SegmentSize"), aAny );
2094 
2095                 // copy the temporary storage into the disk spanned package
2096                 GetStorage()->copyToStorage( xStor );
2097                 uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
2098                 if ( xTrans.is() )
2099                     xTrans->commit();
2100 
2101             }
2102             catch ( uno::Exception& )
2103             {
2104                 //TODO/MBA: error handling
2105             }
2106             return;
2107         }
2108 
2109         INetURLObject aDest( GetURLObject() );
2110 
2111         // source is the temp file written so far
2112         INetURLObject aSource( aNameURL );
2113 
2114 		// a special case, an interaction handler should be used for
2115 		// authentication in case it is available
2116 		Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
2117        	Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
2118         if (xInteractionHandler.is())
2119 			xComEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler,
2120 													  Reference< ::com::sun::star::ucb::XProgressHandler >() );
2121 
2122         if ( ::utl::LocalFileHelper::IsLocalFile( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) || !aDest.removeSegment() )
2123 		{
2124 			TransactedTransferForFS_Impl( aSource, aDest, xComEnv );
2125 		}
2126 		else
2127         {
2128             // create content for the parent folder and call transfer on that content with the source content
2129             // and the destination file name as parameters
2130             ::ucbhelper::Content aSourceContent;
2131             ::ucbhelper::Content aTransferContent;
2132 
2133             String aFileName = GetLongName();
2134             if ( !aFileName.Len() )
2135                 aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2136 
2137 			try
2138 			{
2139 				aTransferContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
2140 			}
2141 			catch (const ::com::sun::star::ucb::ContentCreationException& ex)
2142             {
2143 				eError = ERRCODE_IO_GENERAL;
2144 				if (
2145 					(ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER    ) ||
2146 					(ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
2147 				   )
2148 				{
2149 					eError = ERRCODE_IO_NOTEXISTSPATH;
2150 				}
2151             }
2152             catch (const ::com::sun::star::uno::Exception&)
2153             {
2154                 eError = ERRCODE_IO_GENERAL;
2155             }
2156 
2157             if ( !eError || (eError & ERRCODE_WARNING_MASK) )
2158             {
2159                 // free resources, otherwise the transfer may fail
2160                 if ( pImp->xStorage.is() )
2161                     CloseStorage();
2162 
2163                 CloseStreams_Impl();
2164 
2165                 ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent );
2166 
2167                 // check for external parameters that may customize the handling of NameClash situations
2168                 SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
2169                 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
2170                 sal_Int32 nNameClash;
2171                 if ( pOverWrite && !pOverWrite->GetValue() )
2172                     // argument says: never overwrite
2173                     nNameClash = NameClash::ERROR;
2174                 else if ( pRename && pRename->GetValue() )
2175                     // argument says: rename file
2176                     nNameClash = NameClash::RENAME;
2177                 else
2178                     // default is overwrite existing files
2179                     nNameClash = NameClash::OVERWRITE;
2180 
2181                 try
2182                 {
2183                     if (!aTransferContent.transferContent( aSourceContent, ::ucbhelper::InsertOperation_COPY, aFileName, nNameClash ))
2184 						eError = ERRCODE_IO_GENERAL;
2185                 }
2186                 catch ( ::com::sun::star::ucb::CommandAbortedException& )
2187                 {
2188                     eError = ERRCODE_ABORT;
2189                 }
2190                 catch ( ::com::sun::star::ucb::CommandFailedException& )
2191                 {
2192                     eError = ERRCODE_ABORT;
2193                 }
2194                 catch ( ::com::sun::star::ucb::InteractiveIOException& r )
2195                 {
2196                     if ( r.Code == IOErrorCode_ACCESS_DENIED )
2197                         eError = ERRCODE_IO_ACCESSDENIED;
2198                     else if ( r.Code == IOErrorCode_NOT_EXISTING )
2199                         eError = ERRCODE_IO_NOTEXISTS;
2200                     else if ( r.Code == IOErrorCode_CANT_READ )
2201                         eError = ERRCODE_IO_CANTREAD;
2202                     else
2203                         eError = ERRCODE_IO_GENERAL;
2204                 }
2205                 catch ( ::com::sun::star::uno::Exception& )
2206                 {
2207                     eError = ERRCODE_IO_GENERAL;
2208                 }
2209 
2210 				// do not switch from temporary file in case of nonfile protocol
2211 	    	}
2212 		}
2213 
2214         if ( ( !eError || (eError & ERRCODE_WARNING_MASK) ) && !pImp->pTempFile )
2215 		{
2216 			// without a TempFile the physical and logical name should be the same after successful transfer
2217   			::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
2218 														  	aName );
2219 			pImp->m_bSalvageMode = sal_False;
2220 		}
2221     }
2222 }
2223 
2224 //------------------------------------------------------------------
DoInternalBackup_Impl(const::ucbhelper::Content & aOriginalContent,const String & aPrefix,const String & aExtension,const String & aDestDir)2225 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent,
2226 									   const String& aPrefix,
2227 									   const String& aExtension,
2228 									   const String& aDestDir )
2229 {
2230 	RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoInternalBackup_Impl( with destdir )" );
2231 
2232 	if ( pImp->m_aBackupURL.getLength() )
2233 		return; // the backup was done already
2234 
2235 	::utl::TempFile aTransactTemp( aPrefix, &aExtension, &aDestDir );
2236 	aTransactTemp.EnableKillingFile( sal_False );
2237 
2238 	INetURLObject aBackObj( aTransactTemp.GetURL() );
2239 	::rtl::OUString aBackupName = aBackObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2240 
2241 	Reference < ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
2242 	::ucbhelper::Content aBackupCont;
2243 	if( ::ucbhelper::Content::create( aDestDir, xDummyEnv, aBackupCont ) )
2244 	{
2245 		try
2246 		{
2247 			if( aBackupCont.transferContent( aOriginalContent,
2248 											::ucbhelper::InsertOperation_COPY,
2249 											aBackupName,
2250 											NameClash::OVERWRITE ) )
2251 			{
2252 				pImp->m_aBackupURL = aBackObj.GetMainURL( INetURLObject::NO_DECODE );
2253 				pImp->m_bRemoveBackup = sal_True;
2254 			}
2255 		}
2256 		catch( Exception& )
2257 		{}
2258 	}
2259 
2260 	if ( !pImp->m_aBackupURL.getLength() )
2261 		aTransactTemp.EnableKillingFile( sal_True );
2262 }
2263 
2264 //------------------------------------------------------------------
DoInternalBackup_Impl(const::ucbhelper::Content & aOriginalContent)2265 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent )
2266 {
2267 	if ( pImp->m_aBackupURL.getLength() )
2268 		return; // the backup was done already
2269 
2270 	::rtl::OUString aFileName =  GetURLObject().getName( INetURLObject::LAST_SEGMENT,
2271 														true,
2272 														INetURLObject::NO_DECODE );
2273 
2274 	sal_Int32 nPrefixLen = aFileName.lastIndexOf( '.' );
2275 	String aPrefix = ( nPrefixLen == -1 ) ? aFileName : aFileName.copy( 0, nPrefixLen );
2276 	String aExtension = ( nPrefixLen == -1 ) ? String() : String(aFileName.copy( nPrefixLen ));
2277    	String aBakDir = SvtPathOptions().GetBackupPath();
2278 
2279 	DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aBakDir );
2280 
2281 	if ( !pImp->m_aBackupURL.getLength() )
2282 	{
2283 		// the copiing to the backup catalog failed ( for example because
2284 		// of using an encrypted partition as target catalog )
2285 		// since the user did not specify to make backup explicitly
2286 		// office should try to make backup in another place,
2287 		// target catalog does not look bad for this case ( and looks
2288 		// to be the only way for encrypted partitions )
2289 
2290 		INetURLObject aDest = GetURLObject();
2291 		if ( aDest.removeSegment() )
2292 			DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aDest.GetMainURL( INetURLObject::NO_DECODE ) );
2293 	}
2294 }
2295 
2296 
2297 //------------------------------------------------------------------
DoBackup_Impl()2298 void SfxMedium::DoBackup_Impl()
2299 {
2300 	RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoBackup_Impl" );
2301 
2302    	// source file name is the logical name of this medium
2303     INetURLObject aSource( GetURLObject() );
2304 
2305 	// there is nothing to backup in case source file does not exist
2306 	if ( !::utl::UCBContentHelper::IsDocument( aSource.GetMainURL( INetURLObject::NO_DECODE ) ) )
2307 		return;
2308 
2309     sal_Bool        bSuccess = sal_False;
2310 
2311     // get path for backups
2312     String aBakDir = SvtPathOptions().GetBackupPath();
2313     if( aBakDir.Len() )
2314     {
2315         // create content for the parent folder ( = backup folder )
2316         ::ucbhelper::Content  aContent;
2317         Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
2318         if( ::ucbhelper::Content::create( aBakDir, xEnv, aContent ) )
2319 		{
2320         	// save as ".bak" file
2321         	INetURLObject aDest( aBakDir );
2322         	aDest.insertName( aSource.getName() );
2323         	aDest.setExtension( DEFINE_CONST_UNICODE( "bak" ) );
2324         	String aFileName = aDest.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2325 
2326         	// create a content for the source file
2327         	::ucbhelper::Content aSourceContent;
2328         	if ( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent ) )
2329         	{
2330             	try
2331             	{
2332                 	// do the transfer ( copy source file to backup dir )
2333                 	bSuccess = aContent.transferContent( aSourceContent,
2334 														::ucbhelper::InsertOperation_COPY,
2335 														aFileName,
2336 														NameClash::OVERWRITE );
2337 					if( bSuccess )
2338 					{
2339 						pImp->m_aBackupURL = aDest.GetMainURL( INetURLObject::NO_DECODE );
2340 						pImp->m_bRemoveBackup = sal_False;
2341 					}
2342             	}
2343             	catch ( ::com::sun::star::uno::Exception& )
2344             	{
2345             	}
2346         	}
2347     	}
2348 	}
2349 
2350     if ( !bSuccess )
2351 	{
2352 		eError = ERRCODE_SFX_CANTCREATEBACKUP;
2353 	}
2354 }
2355 
2356 //------------------------------------------------------------------
ClearBackup_Impl()2357 void SfxMedium::ClearBackup_Impl()
2358 {
2359 	if( pImp->m_bRemoveBackup )
2360 	{
2361 		// currently a document is always stored in a new medium,
2362 		// thus if a backup can not be removed the backup URL should not be cleaned
2363 		if ( pImp->m_aBackupURL.getLength() )
2364 		{
2365 			if ( ::utl::UCBContentHelper::Kill( pImp->m_aBackupURL ) )
2366 			  // || !::utl::UCBContentHelper::IsDocument( pImp->m_aBackupURL ) );
2367 			{
2368 				pImp->m_bRemoveBackup = sal_False;
2369 				pImp->m_aBackupURL = ::rtl::OUString();
2370 			}
2371 			else
2372 			{
2373 
2374 				DBG_ERROR("Couldn't remove backup file!");
2375 			}
2376 		}
2377 	}
2378 	else
2379 		pImp->m_aBackupURL = ::rtl::OUString();
2380 }
2381 
2382 //----------------------------------------------------------------
GetLockingStream_Impl()2383 void SfxMedium::GetLockingStream_Impl()
2384 {
2385     if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
2386       && !pImp->m_xLockingStream.is() )
2387     {
2388         SFX_ITEMSET_ARG( pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, sal_False);
2389         if ( pWriteStreamItem )
2390             pWriteStreamItem->GetValue() >>= pImp->m_xLockingStream;
2391 
2392         if ( !pImp->m_xLockingStream.is() )
2393         {
2394             // open the original document
2395             uno::Sequence< beans::PropertyValue > xProps;
2396             TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
2397             comphelper::MediaDescriptor aMedium( xProps );
2398 
2399             aMedium.addInputStreamOwnLock();
2400 
2401             uno::Reference< io::XInputStream > xInputStream;
2402             aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp->m_xLockingStream;
2403             aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
2404 
2405             if ( !pImp->pTempFile && !aName.Len() )
2406             {
2407                 // the medium is still based on the original file, it makes sense to initialize the streams
2408                 if ( pImp->m_xLockingStream.is() )
2409                     pImp->xStream = pImp->m_xLockingStream;
2410 
2411                 if ( xInputStream.is() )
2412                     pImp->xInputStream = xInputStream;
2413 
2414                 if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2415                     pImp->xInputStream = pImp->xStream->getInputStream();
2416             }
2417         }
2418     }
2419 }
2420 
2421 //----------------------------------------------------------------
GetMedium_Impl()2422 void SfxMedium::GetMedium_Impl()
2423 {
2424     if ( !pInStream )
2425     {
2426         pImp->bDownloadDone = sal_False;
2427         Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
2428 
2429         //TODO/MBA: need support for SID_STREAM
2430         SFX_ITEMSET_ARG( pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, sal_False);
2431         SFX_ITEMSET_ARG( pSet, pInStreamItem, SfxUnoAnyItem, SID_INPUTSTREAM, sal_False);
2432         if ( pWriteStreamItem )
2433         {
2434             pWriteStreamItem->GetValue() >>= pImp->xStream;
2435 
2436             if ( pInStreamItem )
2437                 pInStreamItem->GetValue() >>= pImp->xInputStream;
2438 
2439             if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2440                 pImp->xInputStream = pImp->xStream->getInputStream();
2441         }
2442         else if ( pInStreamItem )
2443         {
2444             pInStreamItem->GetValue() >>= pImp->xInputStream;
2445         }
2446         else
2447         {
2448             uno::Sequence < beans::PropertyValue > xProps;
2449             String aFileName;
2450             if ( aName.Len() )
2451             {
2452                 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aFileName ) )
2453                 {
2454                     DBG_ERROR("Physical name not convertable!");
2455                 }
2456             }
2457             else
2458                 aFileName = GetName();
2459 
2460             // in case the temporary file exists the streams should be initialized from it,
2461             // but the original MediaDescriptor should not be changed
2462             sal_Bool bFromTempFile = ( pImp->pTempFile != NULL );
2463 
2464             if ( !bFromTempFile )
2465             {
2466                 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, aFileName ) );
2467                 if( !(nStorOpenMode & STREAM_WRITE ) )
2468                     GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
2469                 if (xInteractionHandler.is())
2470                     GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER, makeAny(xInteractionHandler) ) );
2471             }
2472 
2473             if ( m_xInputStreamToLoadFrom.is() )
2474             {
2475                 pImp->xInputStream = m_xInputStreamToLoadFrom;
2476                 pImp->xInputStream->skipBytes(0);
2477                 if(m_bIsReadOnly)
2478                     GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
2479 
2480                 // m_xInputStreamToLoadFrom = 0;
2481             }
2482             else
2483             {
2484                 TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
2485                 comphelper::MediaDescriptor aMedium( xProps );
2486 
2487                 if ( pImp->m_xLockingStream.is() && !bFromTempFile )
2488                 {
2489                     // the medium is not based on the temporary file, so the original stream can be used
2490                     pImp->xStream = pImp->m_xLockingStream;
2491                 }
2492                 else
2493                 {
2494                     if ( bFromTempFile )
2495                     {
2496                         aMedium[comphelper::MediaDescriptor::PROP_URL()] <<= ::rtl::OUString( aFileName );
2497                         aMedium.erase( comphelper::MediaDescriptor::PROP_READONLY() );
2498                         aMedium.addInputStream();
2499                     }
2500                     else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
2501                     {
2502                         // use the special locking approach only for file URLs
2503                         aMedium.addInputStreamOwnLock();
2504                     }
2505                     else
2506                     {
2507                         //add acheck for protocol, to see if it's http or https then add
2508                         //the interecation handler to be used by the authentication dialog
2509                         ::rtl::OUString aScheme =  INetURLObject::GetScheme(GetURLObject().GetProtocol());
2510                         if( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) ||
2511                             aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) )
2512                         {
2513                             aMedium[comphelper::MediaDescriptor::PROP_AUTHENTICATIONHANDLER()] <<= GetAuthenticationInteractionHandler();
2514                         }
2515                         aMedium.addInputStream();
2516                     }
2517 
2518                     // the ReadOnly property set in aMedium is ignored
2519                     // the check is done in LockOrigFileOnDemand() for file and non-file URLs
2520 
2521                     //TODO/MBA: what happens if property is not there?!
2522                     aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp->xStream;
2523                     aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp->xInputStream;
2524                 }
2525 
2526                 GetContent();
2527                 if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2528                     pImp->xInputStream = pImp->xStream->getInputStream();
2529             }
2530 
2531             if ( !bFromTempFile )
2532             {
2533                 //TODO/MBA: need support for SID_STREAM
2534                 if ( pImp->xStream.is() )
2535                     GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM, makeAny( pImp->xStream ) ) );
2536 
2537                 GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM, makeAny( pImp->xInputStream ) ) );
2538             }
2539         }
2540 
2541         //TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
2542         if ( !GetError() && !pImp->xStream.is() && !pImp->xInputStream.is() )
2543         {
2544             SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
2545         }
2546 
2547         if ( !GetError() )
2548         {
2549             if ( pImp->xStream.is() )
2550             {
2551                 pInStream = utl::UcbStreamHelper::CreateStream( pImp->xStream );
2552             }
2553             else if ( pImp->xInputStream.is() )
2554             {
2555                 pInStream = utl::UcbStreamHelper::CreateStream( pImp->xInputStream );
2556             }
2557         }
2558 
2559         pImp->bDownloadDone = sal_True;
2560         pImp->aDoneLink.ClearPendingCall();
2561         pImp->aDoneLink.Call( (void*) GetError() );
2562     }
2563 }
2564 
2565 //----------------------------------------------------------------
IsRemote()2566 sal_Bool SfxMedium::IsRemote()
2567 {
2568     return bRemote;
2569 }
2570 
2571 //------------------------------------------------------------------
2572 
SetUpdatePickList(sal_Bool bVal)2573 void SfxMedium::SetUpdatePickList(sal_Bool bVal)
2574 {
2575     if(!pImp)
2576         pImp = new SfxMedium_Impl( this );
2577     pImp->bUpdatePickList = bVal;
2578 }
2579 //------------------------------------------------------------------
2580 
IsUpdatePickList() const2581 sal_Bool SfxMedium::IsUpdatePickList() const
2582 {
2583     return pImp? pImp->bUpdatePickList: sal_True;
2584 }
2585 //----------------------------------------------------------------
2586 
SetDoneLink(const Link & rLink)2587 void SfxMedium::SetDoneLink( const Link& rLink )
2588 {
2589     pImp->aDoneLink = rLink;
2590 }
2591 
2592 //----------------------------------------------------------------
2593 
SetDataAvailableLink(const Link & rLink)2594 void SfxMedium::SetDataAvailableLink( const Link& rLink )
2595 {
2596     pImp->aAvailableLink = rLink;
2597 }
2598 
2599 //----------------------------------------------------------------
StartDownload()2600 void SfxMedium::StartDownload()
2601 {
2602     GetInStream();
2603 }
2604 
DownLoad(const Link & aLink)2605 void SfxMedium::DownLoad( const Link& aLink )
2606 {
2607     SetDoneLink( aLink );
2608     GetInStream();
2609     if ( pInStream && !aLink.IsSet() )
2610     {
2611         while( !pImp->bDownloadDone )
2612             Application::Yield();
2613     }
2614 }
2615 
2616 //------------------------------------------------------------------
Init_Impl()2617 void SfxMedium::Init_Impl()
2618 /*  [Beschreibung]
2619     Setzt in den Logischen Namen eine gueltige ::com::sun::star::util::URL (Falls zuvor ein Filename
2620     drin war) und setzt den physikalschen Namen auf den Filenamen, falls
2621     vorhanden.
2622  */
2623 
2624 {
2625 	Reference< XOutputStream > rOutStream;
2626 
2627     // TODO/LATER: handle lifetime of storages
2628     pImp->bDisposeStorage = sal_False;
2629 
2630     SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False);
2631     if ( pSalvageItem && !pSalvageItem->GetValue().Len() )
2632 	{
2633 		pSalvageItem = NULL;
2634 		pSet->ClearItem( SID_DOC_SALVAGE );
2635 	}
2636 
2637     if( aLogicName.Len() )
2638     {
2639         INetURLObject aUrl( aLogicName );
2640         INetProtocol eProt = aUrl.GetProtocol();
2641         if ( eProt == INET_PROT_NOT_VALID )
2642         {
2643             DBG_ERROR ( "Unknown protocol!" );
2644         }
2645         else
2646         {
2647             if ( aUrl.HasMark() )
2648             {
2649                 aLogicName = aUrl.GetURLNoMark( INetURLObject::NO_DECODE );
2650                 GetItemSet()->Put( SfxStringItem( SID_JUMPMARK, aUrl.GetMark() ) );
2651             }
2652 
2653             // try to convert the URL into a physical name - but never change a physical name
2654             // physical name may be set if the logical name is changed after construction
2655             if ( !aName.Len() )
2656                 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aName );
2657             else {
2658                 DBG_ASSERT( pSalvageItem, "Suspicious change of logical name!" );
2659             }
2660         }
2661     }
2662 
2663     if ( pSalvageItem && pSalvageItem->GetValue().Len() )
2664 	{
2665         aLogicName = pSalvageItem->GetValue();
2666 		DELETEZ( pURLObj );
2667 		pImp->m_bSalvageMode = sal_True;
2668 	}
2669 
2670 	// in case output stream is by mistake here
2671 	// clear the reference
2672     SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
2673 	if( pOutStreamItem
2674 	 && ( !( pOutStreamItem->GetValue() >>= rOutStream )
2675           || !aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL ) )
2676 	{
2677 		pSet->ClearItem( SID_OUTPUTSTREAM );
2678 		DBG_ERROR( "Unexpected Output stream parameter!\n" );
2679 	}
2680 
2681     if ( aLogicName.Len() )
2682     {
2683         // if the logic name is set it should be set in MediaDescriptor as well
2684         SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
2685         if ( !pFileNameItem )
2686         {
2687             // let the ItemSet be created if necessary
2688             GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, INetURLObject( aLogicName ).GetMainURL( INetURLObject::NO_DECODE ) ) );
2689         }
2690     }
2691 
2692     SetIsRemote_Impl();
2693 }
2694 
2695 //------------------------------------------------------------------
SfxMedium()2696 SfxMedium::SfxMedium()
2697 :   IMPL_CTOR( sal_False, 0 ),	// bRoot, pURLObj
2698 
2699     pFilter(0),
2700     pSet(0),
2701     pImp(new SfxMedium_Impl( this ))
2702 {
2703     Init_Impl();
2704 }
2705 //------------------------------------------------------------------
2706 
SfxMedium(const SfxMedium & rMedium,sal_Bool bTemporary)2707 SfxMedium::SfxMedium( const SfxMedium& rMedium, sal_Bool bTemporary )
2708 :   SvRefBase(),
2709     IMPL_CTOR( sal_True,	// bRoot, pURLObj
2710         rMedium.pURLObj ? new INetURLObject(*rMedium.pURLObj) : 0 ),
2711     pImp(new SfxMedium_Impl( this ))
2712 {
2713     bDirect       = rMedium.IsDirect();
2714     nStorOpenMode = rMedium.GetOpenMode();
2715     if ( !bTemporary )
2716         aName = rMedium.aName;
2717 
2718     pImp->bIsTemp = bTemporary;
2719     DBG_ASSERT( ! rMedium.pImp->bIsTemp, "Temporaeres Medium darf nicht kopiert werden" );
2720     aLogicName = rMedium.aLogicName;
2721     pSet =  rMedium.GetItemSet() ? new SfxItemSet(*rMedium.GetItemSet()) : 0;
2722     pFilter = rMedium.pFilter;
2723     Init_Impl();
2724     if( bTemporary )
2725         CreateTempFile( sal_True );
2726 }
2727 
2728 //------------------------------------------------------------------
2729 
UseInteractionHandler(sal_Bool bUse)2730 void SfxMedium::UseInteractionHandler( sal_Bool bUse )
2731 {
2732     pImp->bAllowDefaultIntHdl = bUse;
2733 }
2734 
2735 //------------------------------------------------------------------
2736 
2737 ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >
GetAuthenticationInteractionHandler()2738 SfxMedium::GetAuthenticationInteractionHandler()
2739 {
2740     // search a possible existing handler inside cached item set
2741     if ( pSet )
2742     {
2743         ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xHandler;
2744         SFX_ITEMSET_ARG( pSet, pHandler, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False);
2745         if ( pHandler && (pHandler->GetValue() >>= xHandler) && xHandler.is() )
2746             return xHandler;
2747     }
2748 
2749     // otherwise return cached default handler ... if it exist.
2750     if ( pImp->xCredentialInteraction.is() )
2751         return pImp->xCredentialInteraction;
2752 
2753     // create default handler and cache it!
2754     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
2755     if ( xFactory.is() )
2756     {
2757         pImp->xCredentialInteraction = ::com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler >(
2758             xFactory->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), ::com::sun::star::uno::UNO_QUERY );
2759         return pImp->xCredentialInteraction;
2760     }
2761 
2762 	return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2763 }
2764 
2765 //------------------------------------------------------------------
2766 
2767 ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >
GetInteractionHandler()2768 SfxMedium::GetInteractionHandler()
2769 {
2770     // if interaction isn't allowed explicitly ... return empty reference!
2771     if ( !pImp->bUseInteractionHandler )
2772         return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2773 
2774     // search a possible existing handler inside cached item set
2775     if ( pSet )
2776     {
2777         ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xHandler;
2778         SFX_ITEMSET_ARG( pSet, pHandler, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False);
2779         if ( pHandler && (pHandler->GetValue() >>= xHandler) && xHandler.is() )
2780             return xHandler;
2781     }
2782 
2783     // if default interaction isn't allowed explicitly ... return empty reference!
2784     if ( !pImp->bAllowDefaultIntHdl )
2785         return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2786 
2787     // otherwise return cached default handler ... if it exist.
2788     if ( pImp->xInteraction.is() )
2789         return pImp->xInteraction;
2790 
2791     // create default handler and cache it!
2792     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
2793     if ( xFactory.is() )
2794     {
2795         pImp->xInteraction = ::com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler >(
2796             xFactory->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), ::com::sun::star::uno::UNO_QUERY );
2797         return pImp->xInteraction;
2798     }
2799 
2800 	return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2801 }
2802 
2803 //----------------------------------------------------------------
2804 
SetFilter(const SfxFilter * pFilterP,sal_Bool)2805 void SfxMedium::SetFilter( const SfxFilter* pFilterP, sal_Bool /*bResetOrig*/ )
2806 {
2807     pFilter = pFilterP;
2808     pImp->nFileVersion = 0;
2809 }
2810 
2811 //----------------------------------------------------------------
2812 
GetOrigFilter(sal_Bool bNotCurrent) const2813 const SfxFilter* SfxMedium::GetOrigFilter( sal_Bool bNotCurrent ) const
2814 {
2815     return ( pImp->pOrigFilter || bNotCurrent ) ? pImp->pOrigFilter : pFilter;
2816 }
2817 
2818 //----------------------------------------------------------------
2819 
SetOrigFilter_Impl(const SfxFilter * pOrigFilter)2820 void SfxMedium::SetOrigFilter_Impl( const SfxFilter* pOrigFilter )
2821 {
2822     pImp->pOrigFilter = pOrigFilter;
2823 }
2824 
2825 //------------------------------------------------------------------
2826 
CreatePasswordToModifyHash(const::rtl::OUString & aPasswd,sal_Bool bWriter)2827 sal_uInt32 SfxMedium::CreatePasswordToModifyHash( const ::rtl::OUString& aPasswd, sal_Bool bWriter )
2828 {
2829     sal_uInt32 nHash = 0;
2830 
2831     if ( aPasswd.getLength() )
2832     {
2833         if ( bWriter )
2834         {
2835             nHash = ::comphelper::DocPasswordHelper::GetWordHashAsUINT32( aPasswd );
2836         }
2837         else
2838         {
2839             rtl_TextEncoding nEncoding = RTL_TEXTENCODING_UTF8;
2840 
2841             // if the MS-filter should be used
2842             // use the inconsistent algorithm to find the encoding specified by MS
2843             nEncoding = osl_getThreadTextEncoding();
2844             switch( nEncoding )
2845             {
2846                 case RTL_TEXTENCODING_ISO_8859_15:
2847                 case RTL_TEXTENCODING_MS_874:
2848                 case RTL_TEXTENCODING_MS_1250:
2849                 case RTL_TEXTENCODING_MS_1251:
2850                 case RTL_TEXTENCODING_MS_1252:
2851                 case RTL_TEXTENCODING_MS_1253:
2852                 case RTL_TEXTENCODING_MS_1254:
2853                 case RTL_TEXTENCODING_MS_1255:
2854                 case RTL_TEXTENCODING_MS_1256:
2855                 case RTL_TEXTENCODING_MS_1257:
2856                 case RTL_TEXTENCODING_MS_1258:
2857                 case RTL_TEXTENCODING_SHIFT_JIS:
2858                 case RTL_TEXTENCODING_GB_2312:
2859                 case RTL_TEXTENCODING_BIG5:
2860                     // in case the system uses an encoding from the list above, it should be used
2861                     break;
2862 
2863                 default:
2864                     // in case other encoding is used, use one of the encodings from the list
2865                     nEncoding = RTL_TEXTENCODING_MS_1250;
2866                     break;
2867             }
2868 
2869             nHash = ::comphelper::DocPasswordHelper::GetXLHashAsUINT16( aPasswd, nEncoding );
2870         }
2871     }
2872 
2873     return nHash;
2874 }
2875 
2876 //------------------------------------------------------------------
2877 
Close()2878 void SfxMedium::Close()
2879 {
2880     if ( pImp->xStorage.is() )
2881     {
2882         // don't close the streams if they belong to the
2883         // storage
2884         //TODO/MBA: how to?! Do we need the flag?!
2885         /*
2886         const SvStream *pStream = aStorage->GetSvStream();
2887         if ( pStream && pStream == pInStream )
2888         {
2889 			CloseZipStorage_Impl();
2890             pInStream = NULL;
2891             pImp->xInputStream = Reference < XInputStream >();
2892             pImp->xLockBytes.Clear();
2893             if ( pSet )
2894                 pSet->ClearItem( SID_INPUTSTREAM );
2895             aStorage->SetDeleteStream( sal_True );
2896         }
2897         else if ( pStream && pStream == pOutStream )
2898         {
2899             pOutStream = NULL;
2900             aStorage->SetDeleteStream( sal_True );
2901         } */
2902 
2903         CloseStorage();
2904     }
2905 
2906 	CloseStreams_Impl();
2907 
2908     UnlockFile( sal_False );
2909 }
2910 
CloseAndRelease()2911 void SfxMedium::CloseAndRelease()
2912 {
2913     if ( pImp->xStorage.is() )
2914     {
2915         // don't close the streams if they belong to the
2916         // storage
2917         //TODO/MBA: how to?! Do we need the flag?!
2918         /*
2919         const SvStream *pStream = aStorage->GetSvStream();
2920         if ( pStream && pStream == pInStream )
2921         {
2922 			CloseZipStorage_Impl();
2923             pInStream = NULL;
2924             pImp->xInputStream = Reference < XInputStream >();
2925             pImp->xLockBytes.Clear();
2926             if ( pSet )
2927                 pSet->ClearItem( SID_INPUTSTREAM );
2928             aStorage->SetDeleteStream( sal_True );
2929         }
2930         else if ( pStream && pStream == pOutStream )
2931         {
2932             pOutStream = NULL;
2933             aStorage->SetDeleteStream( sal_True );
2934         } */
2935 
2936         CloseStorage();
2937     }
2938 
2939 	CloseAndReleaseStreams_Impl();
2940 
2941     UnlockFile( sal_True );
2942 }
2943 
UnlockFile(sal_Bool bReleaseLockStream)2944 void SfxMedium::UnlockFile( sal_Bool bReleaseLockStream )
2945 {
2946     //->i126305
2947     //check if the file is local
2948     if ( ::utl::LocalFileHelper::IsLocalFile( aLogicName ) )
2949     {
2950     //<-i126305
2951         if ( pImp->m_xLockingStream.is() )
2952         {
2953             if ( bReleaseLockStream )
2954             {
2955                 try
2956                 {
2957                     uno::Reference< io::XInputStream > xInStream = pImp->m_xLockingStream->getInputStream();
2958                     uno::Reference< io::XOutputStream > xOutStream = pImp->m_xLockingStream->getOutputStream();
2959                     if ( xInStream.is() )
2960                         xInStream->closeInput();
2961                     if ( xOutStream.is() )
2962                         xOutStream->closeOutput();
2963                 }
2964                 catch( uno::Exception& )
2965                 {}
2966             }
2967 
2968             pImp->m_xLockingStream = uno::Reference< io::XStream >();
2969         }
2970 
2971         if ( pImp->m_bLocked )
2972         {
2973             try
2974             {
2975                 pImp->m_bLocked = sal_False;
2976                 ::svt::DocumentLockFile aLockFile( aLogicName );
2977                 // TODO/LATER: A warning could be shown in case the file is not the own one
2978                 aLockFile.RemoveFile();
2979             }
2980             catch( uno::Exception& )
2981             {}
2982         }
2983     //->i126305
2984     }
2985     else
2986     {
2987         //not local, check if webdav
2988         ::rtl::OUString aScheme =  INetURLObject::GetScheme(GetURLObject().GetProtocol());
2989         if( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) ||
2990             aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) )
2991         {
2992             if ( pImp->m_bLocked )
2993             {
2994                 // an interaction handler should be used for authentication
2995                 try {
2996                     Reference< ::com::sun::star::task::XInteractionHandler > xHandler = GetAuthenticationInteractionHandler();
2997                     Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
2998                     xComEnv = new ::ucbhelper::CommandEnvironment( xHandler,
2999                                                                    Reference< ::com::sun::star::ucb::XProgressHandler >() );
3000                     ::ucbhelper::Content aContentToUnlock( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xComEnv);
3001                     pImp->m_bLocked = sal_False;
3002                     aContentToUnlock.unlock();
3003                 }
3004                 catch (ucb::InteractiveNetworkReadException& e)
3005                 {
3006                     //signalled when this resource can not be unlocked, for whatever reason
3007                 }
3008                 catch( uno::Exception& )
3009                 {}
3010             }
3011         }
3012     }
3013     //<-i126305
3014 }
3015 
CloseAndReleaseStreams_Impl()3016 void SfxMedium::CloseAndReleaseStreams_Impl()
3017 {
3018 	CloseZipStorage_Impl();
3019 
3020 	uno::Reference< io::XInputStream > xInToClose = pImp->xInputStream;
3021 	uno::Reference< io::XOutputStream > xOutToClose;
3022 	if ( pImp->xStream.is() )
3023     {
3024 		xOutToClose = pImp->xStream->getOutputStream();
3025 
3026         // if the locking stream is closed here the related member should be cleaned
3027         if ( pImp->xStream == pImp->m_xLockingStream )
3028             pImp->m_xLockingStream = uno::Reference< io::XStream >();
3029     }
3030 
3031 	// The probably exsisting SvStream wrappers should be closed first
3032     CloseStreams_Impl();
3033 
3034     // in case of salvage mode the storage is based on the streams
3035     if ( !pImp->m_bSalvageMode )
3036     {
3037         try
3038         {
3039             if ( xInToClose.is() )
3040                 xInToClose->closeInput();
3041             if ( xOutToClose.is() )
3042                 xOutToClose->closeOutput();
3043         }
3044         catch ( uno::Exception& )
3045         {
3046         }
3047     }
3048 }
3049 
3050 //------------------------------------------------------------------
CloseStreams_Impl()3051 void SfxMedium::CloseStreams_Impl()
3052 {
3053 	CloseInStream_Impl();
3054 	CloseOutStream_Impl();
3055 
3056     if ( pSet )
3057         pSet->ClearItem( SID_CONTENT );
3058 
3059     pImp->aContent = ::ucbhelper::Content();
3060 }
3061 
3062 //------------------------------------------------------------------
3063 
RefreshName_Impl()3064 void SfxMedium::RefreshName_Impl()
3065 {
3066 #if 0   //(dv)
3067     if ( pImp->aContent.get().is() )
3068     {
3069         String aNameP = pImp->xAnchor->GetViewURL();
3070         pImp->aOrigURL = aNameP;
3071         aLogicName = aNameP;
3072         DELETEZ( pURLObj );
3073         if (aLogicName.Len())
3074             aLogicName = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
3075         SetIsRemote_Impl();
3076     }
3077 #endif  //(dv)
3078 }
3079 
SetIsRemote_Impl()3080 void SfxMedium::SetIsRemote_Impl()
3081 {
3082     INetURLObject aObj( GetName() );
3083     switch( aObj.GetProtocol() )
3084     {
3085         case INET_PROT_FTP:
3086         case INET_PROT_HTTP:
3087         case INET_PROT_HTTPS:
3088         case INET_PROT_POP3:
3089         case INET_PROT_NEWS:
3090         case INET_PROT_IMAP:
3091 //        case INET_PROT_OUT:
3092         case INET_PROT_VIM:
3093             bRemote = sal_True; break;
3094         default:
3095             bRemote = ( GetName().CompareToAscii( "private:msgid", 13 ) == COMPARE_EQUAL );
3096             break;
3097     }
3098 
3099     // Da Dateien, die Remote geschrieben werden zur Uebertragung auch
3100     // gelesen werden koennen muessen
3101     if( bRemote )
3102         nStorOpenMode |= STREAM_READ;
3103 }
3104 
3105 
3106 
SetName(const String & aNameP,sal_Bool bSetOrigURL)3107 void SfxMedium::SetName( const String& aNameP, sal_Bool bSetOrigURL )
3108 {
3109     if( !pImp->aOrigURL.Len() )
3110         pImp->aOrigURL = aLogicName;
3111     if( bSetOrigURL )
3112         pImp->aOrigURL = aNameP;
3113     aLogicName = aNameP;
3114     DELETEZ( pURLObj );
3115     pImp->aContent = ::ucbhelper::Content();
3116     Init_Impl();
3117 }
3118 
3119 //----------------------------------------------------------------
GetOrigURL() const3120 const String& SfxMedium::GetOrigURL() const
3121 {
3122     return !pImp->aOrigURL.Len() ? (String &)aLogicName : pImp->aOrigURL;
3123 }
3124 
3125 //----------------------------------------------------------------
3126 
SetPhysicalName_Impl(const String & rNameP)3127 void SfxMedium::SetPhysicalName_Impl( const String& rNameP )
3128 {
3129     if ( rNameP != aName )
3130     {
3131         if( pImp->pTempFile )
3132         {
3133             delete pImp->pTempFile;
3134             pImp->pTempFile = NULL;
3135         }
3136 
3137         if ( aName.Len() || rNameP.Len() )
3138             pImp->aContent = ::ucbhelper::Content();
3139 
3140         aName = rNameP;
3141         bTriedStorage = sal_False;
3142         pImp->bIsStorage = sal_False;
3143     }
3144 }
3145 
3146 //------------------------------------------------------------------
SetTemporary(sal_Bool bTemp)3147 void SfxMedium::SetTemporary( sal_Bool bTemp )
3148 {
3149     pImp->bIsTemp = bTemp;
3150 }
3151 
3152 //------------------------------------------------------------------
IsTemporary() const3153 sal_Bool SfxMedium::IsTemporary() const
3154 {
3155     return pImp->bIsTemp;
3156 }
3157 
3158 //------------------------------------------------------------------
3159 
Exists(sal_Bool)3160 sal_Bool SfxMedium::Exists( sal_Bool /*bForceSession*/ )
3161 {
3162     DBG_ERROR( "Not implemented!" );
3163     return sal_True;
3164 }
3165 
3166 //------------------------------------------------------------------
3167 
ReOpen()3168 void SfxMedium::ReOpen()
3169 {
3170     sal_Bool bUseInteractionHandler = pImp->bUseInteractionHandler;
3171     pImp->bUseInteractionHandler = sal_False;
3172     GetMedium_Impl();
3173     pImp->bUseInteractionHandler = bUseInteractionHandler;
3174 }
3175 
3176 //------------------------------------------------------------------
3177 
CompleteReOpen()3178 void SfxMedium::CompleteReOpen()
3179 {
3180 	// do not use temporary file for reopen and in case of success throw the temporary file away
3181     sal_Bool bUseInteractionHandler = pImp->bUseInteractionHandler;
3182     pImp->bUseInteractionHandler = sal_False;
3183 
3184     ::utl::TempFile* pTmpFile = NULL;
3185 	if ( pImp->pTempFile )
3186 	{
3187 		pTmpFile = pImp->pTempFile;
3188 		pImp->pTempFile = NULL;
3189 		aName = String();
3190 	}
3191 
3192     GetMedium_Impl();
3193 
3194 	if ( GetError() )
3195 	{
3196 		if ( pImp->pTempFile )
3197 		{
3198     		pImp->pTempFile->EnableKillingFile( sal_True );
3199 			delete pImp->pTempFile;
3200 		}
3201 		pImp->pTempFile = pTmpFile;
3202         if ( pImp->pTempFile )
3203             aName = pImp->pTempFile->GetFileName();
3204 	}
3205 	else
3206 	{
3207 		pTmpFile->EnableKillingFile( sal_True );
3208 		delete pTmpFile;
3209 
3210 	}
3211 
3212     pImp->bUseInteractionHandler = bUseInteractionHandler;
3213 }
3214 
3215 //------------------------------------------------------------------
SfxMedium(const String & rName,StreamMode nOpenMode,sal_Bool bDirectP,const SfxFilter * pFlt,SfxItemSet * pInSet)3216 SfxMedium::SfxMedium
3217 (
3218     const String &rName, StreamMode nOpenMode,  sal_Bool bDirectP,
3219     const SfxFilter *pFlt, SfxItemSet *pInSet
3220 )
3221 :   IMPL_CTOR( sal_False, 0 ),	// bRoot, pURLObj
3222     pFilter(pFlt),
3223     pSet( pInSet ),
3224     pImp(new SfxMedium_Impl( this ))
3225 {
3226     aLogicName = rName;
3227     nStorOpenMode = nOpenMode;
3228     bDirect = bDirectP;
3229     Init_Impl();
3230 }
3231 
3232 
SfxMedium(const::com::sun::star::uno::Sequence<::com::sun::star::beans::PropertyValue> & aArgs)3233 SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
3234     : IMPL_CTOR( sal_False, 0 ),  // bRoot, pURLObj
3235     pFilter(0),
3236     pSet(0),
3237     pImp(new SfxMedium_Impl( this ))
3238 {
3239     SfxAllItemSet *pParams = new SfxAllItemSet( SFX_APP()->GetPool() );
3240     pSet = pParams;
3241     TransformParameters( SID_OPENDOC, aArgs, *pParams );
3242 
3243     String aFilterName;
3244     SFX_ITEMSET_ARG( pSet, pFilterNameItem, SfxStringItem, SID_FILTER_NAME, sal_False );
3245     if( pFilterNameItem )
3246         aFilterName = pFilterNameItem->GetValue();
3247     pFilter = SFX_APP()->GetFilterMatcher().GetFilter4FilterName( aFilterName );
3248 
3249     sal_Bool bSalvage = sal_False;
3250     SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False );
3251     if( pSalvageItem )
3252     {
3253         // QUESTION: there is some treatment of Salvage in Init_Impl; align!
3254         bSalvage = sal_True;
3255         if ( pSalvageItem->GetValue().Len() )
3256         {
3257             // if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
3258             // that must be copied here
3259 
3260             SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
3261             if (!pFileNameItem) throw uno::RuntimeException();
3262             ::rtl::OUString aNewTempFileURL = SfxMedium::CreateTempCopyWithExt( pFileNameItem->GetValue() );
3263             if ( aNewTempFileURL.getLength() )
3264             {
3265                 pSet->Put( SfxStringItem( SID_FILE_NAME, aNewTempFileURL ) );
3266                 pSet->ClearItem( SID_INPUTSTREAM );
3267                 pSet->ClearItem( SID_STREAM );
3268                 pSet->ClearItem( SID_CONTENT );
3269             }
3270             else
3271             {
3272                 OSL_ENSURE( sal_False, "Can not create a new temporary file for crash recovery!\n" );
3273             }
3274         }
3275     }
3276 
3277     sal_Bool bReadOnly = sal_False;
3278     SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
3279     if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
3280         bReadOnly = sal_True;
3281 
3282     SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
3283     if (!pFileNameItem) throw uno::RuntimeException();
3284     aLogicName = pFileNameItem->GetValue();
3285     nStorOpenMode = bReadOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
3286     bDirect = sal_False;
3287     Init_Impl();
3288 }
3289 
3290 
3291 //------------------------------------------------------------------
3292 
SfxMedium(const uno::Reference<embed::XStorage> & rStor,const String & rBaseURL,const SfxItemSet * p,sal_Bool bRootP)3293 SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const String& rBaseURL, const SfxItemSet* p, sal_Bool bRootP )
3294 :   IMPL_CTOR( bRootP, 0 ),	// bRoot, pURLObj
3295     pSet(0),
3296     pImp( new SfxMedium_Impl( this ))
3297 {
3298     String aType = SfxFilter::GetTypeFromStorage( rStor );
3299 	pFilter = SFX_APP()->GetFilterMatcher().GetFilter4EA( aType );
3300     DBG_ASSERT( pFilter, "No Filter for storage found!" );
3301 
3302     Init_Impl();
3303     pImp->xStorage = rStor;
3304     pImp->bDisposeStorage = sal_False;
3305 
3306     // always take BaseURL first, could be overwritten by ItemSet
3307     GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
3308     if ( p )
3309         GetItemSet()->Put( *p );
3310 }
3311 
SfxMedium(const uno::Reference<embed::XStorage> & rStor,const String & rBaseURL,const String & rTypeName,const SfxItemSet * p,sal_Bool bRootP)3312 SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const String& rBaseURL, const String& rTypeName, const SfxItemSet* p, sal_Bool bRootP )
3313 :   IMPL_CTOR( bRootP, 0 ),	// bRoot, pURLObj
3314     pSet(0),
3315     pImp( new SfxMedium_Impl( this ))
3316 {
3317 	pFilter = SFX_APP()->GetFilterMatcher().GetFilter4EA( rTypeName );
3318     DBG_ASSERT( pFilter, "No Filter for storage found!" );
3319 
3320     Init_Impl();
3321     pImp->xStorage = rStor;
3322     pImp->bDisposeStorage = sal_False;
3323 
3324     // always take BaseURL first, could be overwritten by ItemSet
3325     GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
3326     if ( p )
3327         GetItemSet()->Put( *p );
3328 }
3329 
3330 //------------------------------------------------------------------
3331 
~SfxMedium()3332 SfxMedium::~SfxMedium()
3333 {
3334     /* Attention
3335         Don't enable CancelTransfers() till you know that the writer/web has changed his asynchronous load
3336         behaviour. Otherwise maybe StyleSheets inside a html file will not be loaded at the right time.
3337         => further the help will be empty then ... #100490#
3338      */
3339     //CancelTransfers();
3340 
3341 	// if there is a requirement to clean the backup this is the last possibility to do it
3342 	ClearBackup_Impl();
3343 
3344     Close();
3345 
3346     delete pSet;
3347 
3348     if( pImp->bIsTemp && aName.Len() )
3349     {
3350         String aTemp;
3351         if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aTemp ))
3352         {
3353 			DBG_ERROR("Physical name not convertable!");
3354         }
3355 
3356         if ( !::utl::UCBContentHelper::Kill( aTemp ) )
3357         {
3358 			DBG_ERROR("Couldn't remove temporary file!");
3359         }
3360     }
3361 
3362     pFilter = 0;
3363 
3364     delete pURLObj;
3365     delete pImp;
3366 }
3367 
3368 //------------------------------------------------------------------
SetItemSet(SfxItemSet * pNewSet)3369 void SfxMedium::SetItemSet(SfxItemSet *pNewSet)
3370 {
3371     delete pSet;
3372     pSet = pNewSet;
3373 }
3374 
3375 //----------------------------------------------------------------
GetURLObject() const3376 const INetURLObject& SfxMedium::GetURLObject() const
3377 {
3378     if( !pURLObj )
3379     {
3380         SfxMedium* pThis = const_cast < SfxMedium* > (this);
3381         pThis->pURLObj = new INetURLObject( aLogicName );
3382 		if ( pThis->pURLObj->HasMark() )
3383 			(*pThis->pURLObj) = INetURLObject( aLogicName ).GetURLNoMark();
3384     }
3385 
3386     return *pURLObj;
3387 }
3388 
3389 //----------------------------------------------------------------
3390 
GetPreRedirectedURL() const3391 const String& SfxMedium::GetPreRedirectedURL() const
3392 {
3393     return pImp->aPreRedirectionURL;
3394 }
3395 //----------------------------------------------------------------
3396 
GetMIMEAndRedirect(String &)3397 sal_uInt32 SfxMedium::GetMIMEAndRedirect( String& /*rName*/ )
3398 {
3399 /* dv !!!! not needed any longer ?
3400     INetProtocol eProt = GetURLObject().GetProtocol();
3401     if( eProt == INET_PROT_FTP && SvBinding::ShouldUseFtpProxy( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
3402     {
3403         Any aAny( UCB_Helper::GetProperty( GetContent(), WID_FLAG_IS_FOLDER ) );
3404         sal_Bool bIsFolder = sal_False;
3405         if ( ( aAny >>= bIsFolder ) && bIsFolder )
3406             return ERRCODE_NONE;
3407     }
3408 
3409     GetMedium_Impl();
3410     if( !eError && pImp->xBinding.Is() )
3411     {
3412         eError = pImp->xBinding->GetMimeType( rName );
3413 
3414         // Wir koennen keine Parameter wie CharSets usw.
3415         rName = rName.GetToken( 0, ';' );
3416         if( !eError )
3417         {
3418             if( !pImp->aPreRedirectionURL.Len() )
3419                 pImp->aPreRedirectionURL = aLogicName;
3420             SetName( pImp->xBinding->GetRedirectedURL() );
3421         }
3422         pImp->aExpireTime = pImp->xBinding->GetExpireDateTime();
3423     }
3424     return eError;
3425 */
3426     return 0;
3427 }
3428 
3429 //----------------------------------------------------------------
3430 
SetReferer(const String & rRefer)3431 void SfxMedium::SetReferer( const String& rRefer )
3432 {
3433     pImp->aReferer = rRefer;
3434 }
3435 //----------------------------------------------------------------
3436 
GetReferer() const3437 const String& SfxMedium::GetReferer( ) const
3438 {
3439     return pImp->aReferer;
3440 }
3441 
3442 //----------------------------------------------------------------
3443 
SetExpired_Impl(const DateTime & rDateTime)3444 void SfxMedium::SetExpired_Impl( const DateTime& rDateTime )
3445 {
3446     pImp->aExpireTime = rDateTime;
3447 }
3448 //----------------------------------------------------------------
3449 
IsExpired() const3450 sal_Bool SfxMedium::IsExpired() const
3451 {
3452     return pImp->aExpireTime.IsValid() && pImp->aExpireTime < DateTime();
3453 }
3454 //----------------------------------------------------------------
3455 
ForceSynchronStream_Impl(sal_Bool bForce)3456 void SfxMedium::ForceSynchronStream_Impl( sal_Bool bForce )
3457 {
3458     if( pInStream )
3459     {
3460         SvLockBytes* pBytes = pInStream->GetLockBytes();
3461         if( pBytes )
3462             pBytes->SetSynchronMode( bForce );
3463     }
3464     pImp->bForceSynchron = bForce;
3465 }
3466 
3467 //----------------------------------------------------------------
GetLoadTargetFrame() const3468 SfxFrame* SfxMedium::GetLoadTargetFrame() const
3469 {
3470     return pImp->wLoadTargetFrame;
3471 }
3472 //----------------------------------------------------------------
3473 
SetLoadTargetFrame(SfxFrame * pFrame)3474 void SfxMedium::SetLoadTargetFrame(SfxFrame* pFrame )
3475 {
3476     pImp->wLoadTargetFrame = pFrame;
3477 }
3478 //----------------------------------------------------------------
3479 
SetStorage_Impl(const uno::Reference<embed::XStorage> & rStor)3480 void SfxMedium::SetStorage_Impl( const uno::Reference < embed::XStorage >& rStor )
3481 {
3482     pImp->xStorage = rStor;
3483 }
3484 //----------------------------------------------------------------
3485 
GetItemSet() const3486 SfxItemSet* SfxMedium::GetItemSet() const
3487 {
3488 	// this method *must* return an ItemSet, returning NULL can cause crashes
3489     if( !pSet )
3490 		((SfxMedium*)this)->pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
3491     return pSet;
3492 }
3493 //----------------------------------------------------------------
3494 
GetHeaderAttributes_Impl()3495 SvKeyValueIterator* SfxMedium::GetHeaderAttributes_Impl()
3496 {
3497     if( !pImp->xAttributes.Is() )
3498 	{
3499 		pImp->xAttributes = SvKeyValueIteratorRef( new SvKeyValueIterator );
3500 
3501 		if ( GetContent().is() )
3502 		{
3503 			pImp->bIsCharsetInitialized = sal_True;
3504 
3505 			try
3506 			{
3507 				Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
3508 				::rtl::OUString aContentType;
3509 				aAny >>= aContentType;
3510 
3511 				pImp->xAttributes->Append( SvKeyValue( ::rtl::OUString::createFromAscii( "content-type" ), aContentType ) );
3512 			}
3513 			catch ( ::com::sun::star::uno::Exception& )
3514 			{
3515 			}
3516 		}
3517 	}
3518 
3519     return pImp->xAttributes;
3520 }
3521 //----------------------------------------------------------------
3522 
GetHdl()3523 SvCompatWeakHdl* SfxMedium::GetHdl()
3524 {
3525     return pImp->GetHdl();
3526 }
3527 
IsDownloadDone_Impl()3528 sal_Bool SfxMedium::IsDownloadDone_Impl()
3529 {
3530     return pImp->bDownloadDone;
3531 }
3532 
GetInputStream()3533 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >  SfxMedium::GetInputStream()
3534 {
3535 	if ( !pImp->xInputStream.is() )
3536 		GetMedium_Impl();
3537     return pImp->xInputStream;
3538 }
3539 
GetVersionList(bool _bNoReload)3540 const uno::Sequence < util::RevisionTag >& SfxMedium::GetVersionList( bool _bNoReload )
3541 {
3542 	// if the medium has no name, then this medium should represent a new document and can have no version info
3543     if ( ( !_bNoReload || !pImp->m_bVersionsAlreadyLoaded ) && !pImp->aVersions.getLength() &&
3544          ( aName.Len() || aLogicName.Len() ) && GetStorage().is() )
3545     {
3546         uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
3547                 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3548         if ( xReader.is() )
3549         {
3550             try
3551             {
3552                 pImp->aVersions = xReader->load( GetStorage() );
3553             }
3554             catch ( uno::Exception& )
3555             {
3556             }
3557         }
3558     }
3559 
3560     if ( !pImp->m_bVersionsAlreadyLoaded )
3561         pImp->m_bVersionsAlreadyLoaded = sal_True;
3562 
3563     return pImp->aVersions;
3564 }
3565 
GetVersionList(const uno::Reference<embed::XStorage> & xStorage)3566 uno::Sequence < util::RevisionTag > SfxMedium::GetVersionList( const uno::Reference < embed::XStorage >& xStorage )
3567 {
3568     uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
3569             ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3570     if ( xReader.is() )
3571     {
3572         try
3573         {
3574             return xReader->load( xStorage );
3575         }
3576         catch ( uno::Exception& )
3577         {
3578         }
3579     }
3580 
3581     return uno::Sequence < util::RevisionTag >();
3582 }
3583 
AddVersion_Impl(util::RevisionTag & rRevision)3584 sal_uInt16 SfxMedium::AddVersion_Impl( util::RevisionTag& rRevision )
3585 {
3586     if ( GetStorage().is() )
3587     {
3588         // Einen eindeutigen Namen f"ur den Stream ermitteln
3589         SvULongs aLongs;
3590         sal_Int32 nLength = pImp->aVersions.getLength();
3591         for ( sal_Int32 m=0; m<nLength; m++ )
3592         {
3593             sal_uInt32 nVer = (sal_uInt32) String( pImp->aVersions[m].Identifier ).Copy(7).ToInt32();
3594             sal_uInt16 n;
3595             for ( n=0; n<aLongs.Count(); n++ )
3596                 if ( nVer<aLongs[n] )
3597                     break;
3598 
3599             aLongs.Insert( nVer, n );
3600         }
3601 
3602         sal_uInt16 nKey;
3603         for ( nKey=0; nKey<aLongs.Count(); nKey++ )
3604             if ( aLongs[nKey] > ( sal_uIntPtr ) nKey+1 )
3605                 break;
3606 
3607         String aRevName = DEFINE_CONST_UNICODE( "Version" );
3608         aRevName += String::CreateFromInt32( nKey + 1 );
3609         pImp->aVersions.realloc( nLength+1 );
3610         rRevision.Identifier = aRevName;
3611         pImp->aVersions[nLength] = rRevision;
3612         return nKey;
3613     }
3614 
3615     return 0;
3616 }
3617 
RemoveVersion_Impl(const::rtl::OUString & rName)3618 sal_Bool SfxMedium::RemoveVersion_Impl( const ::rtl::OUString& rName )
3619 {
3620     if ( !pImp->aVersions.getLength() )
3621         return sal_False;
3622 
3623     sal_Int32 nLength = pImp->aVersions.getLength();
3624     for ( sal_Int32 n=0; n<nLength; n++ )
3625     {
3626         if ( pImp->aVersions[n].Identifier == rName )
3627         {
3628             for ( sal_Int32 m=n; m<nLength-1; m++ )
3629                 pImp->aVersions[m] = pImp->aVersions[m+1];
3630             pImp->aVersions.realloc(nLength-1);
3631             return sal_True;
3632         }
3633     }
3634 
3635     return sal_False;
3636 }
3637 
TransferVersionList_Impl(SfxMedium & rMedium)3638 sal_Bool SfxMedium::TransferVersionList_Impl( SfxMedium& rMedium )
3639 {
3640     if ( rMedium.pImp->aVersions.getLength() )
3641     {
3642         pImp->aVersions = rMedium.pImp->aVersions;
3643         return sal_True;
3644     }
3645 
3646     return sal_False;
3647 }
3648 
SaveVersionList_Impl(sal_Bool)3649 sal_Bool SfxMedium::SaveVersionList_Impl( sal_Bool /*bUseXML*/ )
3650 {
3651     if ( GetStorage().is() )
3652     {
3653         if ( !pImp->aVersions.getLength() )
3654             return sal_True;
3655 
3656         uno::Reference < document::XDocumentRevisionListPersistence > xWriter( comphelper::getProcessServiceFactory()->createInstance(
3657                 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3658         if ( xWriter.is() )
3659         {
3660             try
3661             {
3662                 xWriter->store( GetStorage(), pImp->aVersions );
3663                 return sal_True;
3664             }
3665             catch ( uno::Exception& )
3666             {
3667             }
3668         }
3669     }
3670 
3671     return sal_False;
3672 }
3673 
3674 //----------------------------------------------------------------
IsReadOnly()3675 sal_Bool SfxMedium::IsReadOnly()
3676 {
3677     sal_Bool bReadOnly = sal_False;
3678 
3679     // a) ReadOnly filter can't produce read/write contents!
3680     bReadOnly = (
3681                     (pFilter                                                                         ) &&
3682                     ((pFilter->GetFilterFlags() & SFX_FILTER_OPENREADONLY) == SFX_FILTER_OPENREADONLY)
3683                 );
3684 
3685     // b) if filter allow read/write contents .. check open mode of the storage
3686     if (!bReadOnly)
3687         bReadOnly = !( GetOpenMode() & STREAM_WRITE );
3688 
3689     // c) the API can force the readonly state!
3690     if (!bReadOnly)
3691     {
3692         SFX_ITEMSET_ARG( GetItemSet(), pItem, SfxBoolItem, SID_DOC_READONLY, sal_False);
3693         if (pItem)
3694             bReadOnly = pItem->GetValue();
3695     }
3696 
3697     return bReadOnly;
3698 }
3699 
3700 //----------------------------------------------------------------
SetWritableForUserOnly(const::rtl::OUString & aURL)3701 sal_Bool SfxMedium::SetWritableForUserOnly( const ::rtl::OUString& aURL )
3702 {
3703     // UCB does not allow to allow write access only for the user,
3704     // use osl API
3705     sal_Bool bResult = sal_False;
3706 
3707     ::osl::DirectoryItem aDirItem;
3708     if ( ::osl::DirectoryItem::get( aURL, aDirItem ) == ::osl::FileBase::E_None )
3709     {
3710         ::osl::FileStatus aFileStatus( FileStatusMask_Attributes );
3711         if ( aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None
3712           && aFileStatus.isValid( FileStatusMask_Attributes ) )
3713         {
3714             sal_uInt64 nAttributes = aFileStatus.getAttributes();
3715 
3716             nAttributes &= ~(Attribute_OwnWrite |
3717                              Attribute_GrpWrite |
3718                              Attribute_OthWrite |
3719                              Attribute_ReadOnly);
3720             nAttributes |= Attribute_OwnWrite;
3721 
3722             bResult = ( osl::File::setAttributes( aURL, nAttributes ) == ::osl::FileBase::E_None );
3723         }
3724     }
3725 
3726     return bResult;
3727 }
3728 
3729 //----------------------------------------------------------------
CreateTempFile(sal_Bool bReplace)3730 void SfxMedium::CreateTempFile( sal_Bool bReplace )
3731 {
3732     if ( pImp->pTempFile )
3733     {
3734         if ( !bReplace )
3735             return;
3736 
3737         DELETEZ( pImp->pTempFile );
3738         aName = String();
3739     }
3740 
3741     do
3742     {
3743         pImp->pTempFile = new ::utl::TempFile();
3744         if ( GetName().Equals( pImp->pTempFile->GetURL() ) )
3745         {
3746             delete pImp->pTempFile;
3747             pImp->pTempFile = NULL;
3748         }
3749     } while ( pImp->pTempFile == NULL );
3750     pImp->pTempFile->EnableKillingFile( sal_True );
3751     aName = pImp->pTempFile->GetFileName();
3752     ::rtl::OUString aTmpURL = pImp->pTempFile->GetURL();
3753     if ( !aName.Len() || !aTmpURL.getLength() )
3754     {
3755         SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3756         return;
3757     }
3758 
3759     if ( !( nStorOpenMode & STREAM_TRUNC ) )
3760     {
3761         sal_Bool bTransferSuccess = sal_False;
3762 
3763         if ( GetContent().is()
3764           && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
3765           && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
3766         {
3767             // if there is already such a document, we should copy it
3768             // if it is a file system use OS copy process
3769             try
3770             {
3771                 uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
3772                 INetURLObject aTmpURLObj( aTmpURL );
3773                 ::rtl::OUString aFileName = aTmpURLObj.getName( INetURLObject::LAST_SEGMENT,
3774                                                                 true,
3775                                                                 INetURLObject::DECODE_WITH_CHARSET );
3776                 if ( aFileName.getLength() && aTmpURLObj.removeSegment() )
3777                 {
3778                     ::ucbhelper::Content aTargetContent( aTmpURLObj.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
3779                     if ( aTargetContent.transferContent( pImp->aContent, ::ucbhelper::InsertOperation_COPY, aFileName, NameClash::OVERWRITE ) )
3780                     {
3781                         SetWritableForUserOnly( aTmpURL );
3782                         bTransferSuccess = sal_True;
3783                     }
3784                 }
3785             }
3786             catch( uno::Exception& )
3787             {}
3788 
3789             if ( bTransferSuccess )
3790             {
3791                 CloseOutStream();
3792                 CloseInStream();
3793             }
3794         }
3795 
3796         if ( !bTransferSuccess && pInStream )
3797         {
3798             // the case when there is no URL-access available or this is a remote protocoll
3799             // but there is an input stream
3800             GetOutStream();
3801             if ( pOutStream )
3802             {
3803                 char        *pBuf = new char [8192];
3804                 sal_uInt32   nErr = ERRCODE_NONE;
3805 
3806                 pInStream->Seek(0);
3807                 pOutStream->Seek(0);
3808 
3809                 while( !pInStream->IsEof() && nErr == ERRCODE_NONE )
3810                 {
3811                     sal_uInt32 nRead = pInStream->Read( pBuf, 8192 );
3812                     nErr = pInStream->GetError();
3813                     pOutStream->Write( pBuf, nRead );
3814                 }
3815 
3816                 bTransferSuccess = sal_True;
3817                 delete[] pBuf;
3818                 CloseInStream();
3819             }
3820             CloseOutStream_Impl();
3821         }
3822         else
3823         {
3824             // Quite strange design, but currently it is expected that in this case no transfer happens
3825             // TODO/LATER: get rid of this inconsistent part of the call design
3826             bTransferSuccess = sal_True;
3827             CloseInStream();
3828         }
3829 
3830         if ( !bTransferSuccess )
3831         {
3832             SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3833             return;
3834         }
3835     }
3836 
3837     CloseStorage();
3838 }
3839 
3840 //----------------------------------------------------------------
CreateTempFileNoCopy()3841 void SfxMedium::CreateTempFileNoCopy()
3842 {
3843     // this call always replaces the existing temporary file
3844     if ( pImp->pTempFile )
3845     {
3846         delete pImp->pTempFile;
3847         pImp->pTempFile = NULL;
3848     }
3849 
3850     do
3851     {
3852         pImp->pTempFile = new ::utl::TempFile();
3853         if ( GetName().Equals( pImp->pTempFile->GetURL() ) )
3854         {
3855             delete pImp->pTempFile;
3856             pImp->pTempFile = NULL;
3857         }
3858     } while ( pImp->pTempFile == NULL );
3859     pImp->pTempFile->EnableKillingFile( sal_True );
3860     aName = pImp->pTempFile->GetFileName();
3861     if ( !aName.Len() )
3862     {
3863         SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3864         return;
3865     }
3866 
3867     CloseOutStream_Impl();
3868     CloseStorage();
3869 }
3870 
GetCharset()3871 ::rtl::OUString SfxMedium::GetCharset()
3872 {
3873     if( !pImp->bIsCharsetInitialized )
3874 	{
3875 		// Set an error in case there is no content?
3876 		if ( GetContent().is() )
3877 		{
3878 			pImp->bIsCharsetInitialized = sal_True;
3879 
3880 			try
3881 			{
3882 				Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
3883 				::rtl::OUString aField;
3884 				aAny >>= aField;
3885 
3886 				::rtl::OString sContent = ::rtl::OUStringToOString( aField, RTL_TEXTENCODING_ASCII_US );
3887 				ByteString sType, sSubType;
3888 				INetContentTypeParameterList aParameters;
3889 
3890 				if( INetContentTypes::parse( sContent, sType, sSubType, &aParameters ) )
3891 				{
3892 					const INetContentTypeParameter * pCharset = aParameters.find("charset");
3893 					if (pCharset != 0)
3894 						pImp->aCharset = pCharset->m_sValue;
3895 				}
3896 			}
3897 			catch ( ::com::sun::star::uno::Exception& )
3898 			{
3899 			}
3900 		}
3901 	}
3902 
3903 	return pImp->aCharset;
3904 }
3905 
SetCharset(::rtl::OUString aChs)3906 void SfxMedium::SetCharset( ::rtl::OUString aChs )
3907 {
3908 	pImp->bIsCharsetInitialized = sal_True;
3909 	pImp->aCharset = aChs;
3910 }
3911 
SignContents_Impl(sal_Bool bScriptingContent,const::rtl::OUString & aODFVersion,sal_Bool bHasValidDocumentSignature)3912 sal_Bool SfxMedium::SignContents_Impl( sal_Bool bScriptingContent, const ::rtl::OUString& aODFVersion, sal_Bool bHasValidDocumentSignature )
3913 {
3914     sal_Bool bChanges = sal_False;
3915 
3916     // the medium should be closed to be able to sign, the caller is responsible to close it
3917     if ( !IsOpen() && !GetError() )
3918     {
3919         // The component should know if there was a valid document signature, since
3920         // it should show a warning in this case
3921         uno::Sequence< uno::Any > aArgs( 2 );
3922         aArgs[0] <<= aODFVersion;
3923         aArgs[1] <<= bHasValidDocumentSignature;
3924         ::com::sun::star::uno::Reference< ::com::sun::star::security::XDocumentDigitalSignatures > xSigner(
3925             comphelper::getProcessServiceFactory()->createInstanceWithArguments(
3926                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ),
3927                 aArgs ),
3928             ::com::sun::star::uno::UNO_QUERY );
3929 
3930         if ( xSigner.is() )
3931         {
3932             uno::Reference< embed::XStorage > xWriteableZipStor;
3933             if ( !IsReadOnly() )
3934             {
3935                 // we can reuse the temporary file if there is one already
3936                 CreateTempFile( sal_False );
3937                 GetMedium_Impl();
3938 
3939                 try
3940                 {
3941                     if ( !pImp->xStream.is() )
3942                         throw uno::RuntimeException();
3943 
3944                     xWriteableZipStor = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING, pImp->xStream );
3945                     if ( !xWriteableZipStor.is() )
3946                         throw uno::RuntimeException();
3947 
3948                     uno::Reference< embed::XStorage > xMetaInf = xWriteableZipStor->openStorageElement(
3949                                                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
3950                                                     embed::ElementModes::READWRITE );
3951                     if ( !xMetaInf.is() )
3952                         throw uno::RuntimeException();
3953 
3954                     if ( bScriptingContent )
3955                     {
3956                         // If the signature has already the document signature it will be removed
3957                         // after the scripting signature is inserted.
3958                         uno::Reference< io::XStream > xStream(
3959                             xMetaInf->openStreamElement( xSigner->getScriptingContentSignatureDefaultStreamName(),
3960                                                          embed::ElementModes::READWRITE ),
3961                             uno::UNO_SET_THROW );
3962 
3963                         if ( xSigner->signScriptingContent( GetZipStorageToSign_Impl(), xStream ) )
3964                         {
3965                             // remove the document signature if any
3966                             ::rtl::OUString aDocSigName = xSigner->getDocumentContentSignatureDefaultStreamName();
3967                             if ( aDocSigName.getLength() && xMetaInf->hasByName( aDocSigName ) )
3968                                 xMetaInf->removeElement( aDocSigName );
3969 
3970                             uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
3971                             xTransact->commit();
3972                             xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
3973                             xTransact->commit();
3974 
3975                             // the temporary file has been written, commit it to the original file
3976                             Commit();
3977                             bChanges = sal_True;
3978                         }
3979                     }
3980                     else
3981                     {
3982                          uno::Reference< io::XStream > xStream(
3983                             xMetaInf->openStreamElement( xSigner->getDocumentContentSignatureDefaultStreamName(),
3984                                                          embed::ElementModes::READWRITE ),
3985                             uno::UNO_SET_THROW );
3986 
3987                         if ( xSigner->signDocumentContent( GetZipStorageToSign_Impl(), xStream ) )
3988                         {
3989                             uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
3990                             xTransact->commit();
3991                             xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
3992                             xTransact->commit();
3993 
3994                             // the temporary file has been written, commit it to the original file
3995                             Commit();
3996                             bChanges = sal_True;
3997                         }
3998                     }
3999                 }
4000                 catch ( uno::Exception& )
4001                 {
4002                     OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
4003                 }
4004 
4005                 CloseAndRelease();
4006             }
4007             else
4008             {
4009                 try
4010                 {
4011                     if ( bScriptingContent )
4012                         xSigner->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
4013                     else
4014                         xSigner->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
4015                 }
4016                 catch( uno::Exception& )
4017                 {
4018                     OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
4019                 }
4020             }
4021         }
4022 
4023         ResetError();
4024     }
4025 
4026 	return bChanges;
4027 }
4028 
4029 //----------------------------------------------------------------
GetCachedSignatureState_Impl()4030 sal_uInt16 SfxMedium::GetCachedSignatureState_Impl()
4031 {
4032 	return pImp->m_nSignatureState;
4033 }
4034 
4035 //----------------------------------------------------------------
SetCachedSignatureState_Impl(sal_uInt16 nState)4036 void SfxMedium::SetCachedSignatureState_Impl( sal_uInt16 nState )
4037 {
4038 	pImp->m_nSignatureState = nState;
4039 }
4040 
HasStorage_Impl() const4041 sal_Bool SfxMedium::HasStorage_Impl() const
4042 {
4043     return pImp->xStorage.is();
4044 }
4045 
IsOpen() const4046 sal_Bool SfxMedium::IsOpen() const
4047 {
4048     return pInStream || pOutStream || pImp->xStorage.is();
4049 }
4050 
CreateTempCopyWithExt(const::rtl::OUString & aURL)4051 ::rtl::OUString SfxMedium::CreateTempCopyWithExt( const ::rtl::OUString& aURL )
4052 {
4053 	::rtl::OUString aResult;
4054 
4055 	if ( aURL.getLength() )
4056 	{
4057 		sal_Int32 nPrefixLen = aURL.lastIndexOf( '.' );
4058 		String aExt = ( nPrefixLen == -1 ) ? String() : String( aURL.copy( nPrefixLen ) );
4059 
4060 		::rtl::OUString aNewTempFileURL = ::utl::TempFile( String(), &aExt ).GetURL();
4061 		if ( aNewTempFileURL.getLength() )
4062 		{
4063 			INetURLObject aSource( aURL );
4064 			INetURLObject aDest( aNewTempFileURL );
4065 			::rtl::OUString aFileName = aDest.getName( INetURLObject::LAST_SEGMENT,
4066 														true,
4067 														INetURLObject::DECODE_WITH_CHARSET );
4068 			if ( aFileName.getLength() && aDest.removeSegment() )
4069 			{
4070 				try
4071 				{
4072 					uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
4073 					::ucbhelper::Content aTargetContent( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
4074 					::ucbhelper::Content aSourceContent( aSource.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
4075 					if ( aTargetContent.transferContent( aSourceContent,
4076 														::ucbhelper::InsertOperation_COPY,
4077 														aFileName,
4078 														NameClash::OVERWRITE ) )
4079 					{
4080 						// Success
4081 						aResult = aNewTempFileURL;
4082 					}
4083 				}
4084 				catch( uno::Exception& )
4085 				{}
4086 			}
4087 		}
4088 	}
4089 
4090 	return aResult;
4091 }
4092 
CallApproveHandler(const uno::Reference<task::XInteractionHandler> & xHandler,uno::Any aRequest,sal_Bool bAllowAbort)4093 sal_Bool SfxMedium::CallApproveHandler( const uno::Reference< task::XInteractionHandler >& xHandler, uno::Any aRequest, sal_Bool bAllowAbort )
4094 {
4095     sal_Bool bResult = sal_False;
4096 
4097     if ( xHandler.is() )
4098     {
4099         try
4100         {
4101             uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( bAllowAbort ? 2 : 1 );
4102 
4103             ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove );
4104             aContinuations[ 0 ] = pApprove.get();
4105 
4106             if ( bAllowAbort )
4107             {
4108                 ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort( new ::comphelper::OInteractionAbort );
4109                 aContinuations[ 1 ] = pAbort.get();
4110             }
4111 
4112             xHandler->handle(::framework::InteractionRequest::CreateRequest (aRequest,aContinuations));
4113             bResult = pApprove->wasSelected();
4114         }
4115         catch( const Exception& )
4116         {
4117         }
4118     }
4119 
4120     return bResult;
4121 }
4122 
SwitchDocumentToTempFile()4123 ::rtl::OUString SfxMedium::SwitchDocumentToTempFile()
4124 {
4125     // the method returns empty string in case of failure
4126     ::rtl::OUString aResult;
4127     ::rtl::OUString aOrigURL = aLogicName;
4128 
4129     if ( aOrigURL.getLength() )
4130     {
4131 		sal_Int32 nPrefixLen = aOrigURL.lastIndexOf( '.' );
4132 		String aExt = ( nPrefixLen == -1 ) ? String() : String( aOrigURL.copy( nPrefixLen ) );
4133 		::rtl::OUString aNewURL = ::utl::TempFile( String(), &aExt ).GetURL();
4134 
4135         // TODO/LATER: In future the aLogicName should be set to shared folder URL
4136         //             and a temporary file should be created. Transport_Impl should be impossible then.
4137         if ( aNewURL.getLength() )
4138         {
4139             uno::Reference< embed::XStorage > xStorage = GetStorage();
4140             uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
4141 
4142             if ( xOptStorage.is() )
4143             {
4144                 // TODO/LATER: reuse the pImp->pTempFile if it already exists
4145 				CanDisposeStorage_Impl( sal_False );
4146 				Close();
4147                 SetPhysicalName_Impl( String() );
4148                 SetName( aNewURL );
4149 
4150                 // remove the readonly state
4151                 sal_Bool bWasReadonly = sal_False;
4152                 nStorOpenMode = SFX_STREAM_READWRITE;
4153                 SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
4154                 if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
4155                     bWasReadonly = sal_True;
4156 				GetItemSet()->ClearItem( SID_DOC_READONLY );
4157 
4158                 GetMedium_Impl();
4159 				LockOrigFileOnDemand( sal_False, sal_False );
4160 				CreateTempFile( sal_True );
4161 				GetMedium_Impl();
4162 
4163                 if ( pImp->xStream.is() )
4164                 {
4165                     try
4166                     {
4167                         xOptStorage->writeAndAttachToStream( pImp->xStream );
4168                         pImp->xStorage = xStorage;
4169                         aResult = aNewURL;
4170                     }
4171                     catch( uno::Exception& )
4172                     {}
4173                 }
4174 
4175                 if ( !aResult.getLength() )
4176                 {
4177                     Close();
4178                     SetPhysicalName_Impl( String() );
4179                     SetName( aOrigURL );
4180                     if ( bWasReadonly )
4181                     {
4182                         // set the readonly state back
4183                         nStorOpenMode = SFX_STREAM_READONLY;
4184 						GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY, sal_True));
4185                     }
4186                     GetMedium_Impl();
4187                     pImp->xStorage = xStorage;
4188                 }
4189             }
4190         }
4191     }
4192 
4193     return aResult;
4194 }
4195 
SwitchDocumentToFile(::rtl::OUString aURL)4196 sal_Bool SfxMedium::SwitchDocumentToFile( ::rtl::OUString aURL )
4197 {
4198     // the method is only for storage based documents
4199     sal_Bool bResult = sal_False;
4200     ::rtl::OUString aOrigURL = aLogicName;
4201 
4202     if ( aURL.getLength() && aOrigURL.getLength() )
4203     {
4204         uno::Reference< embed::XStorage > xStorage = GetStorage();
4205         uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
4206 
4207         if ( xOptStorage.is() )
4208         {
4209             // TODO/LATER: reuse the pImp->pTempFile if it already exists
4210             CanDisposeStorage_Impl( sal_False );
4211             Close();
4212             SetPhysicalName_Impl( String() );
4213             SetName( aURL );
4214 
4215             // open the temporary file based document
4216             GetMedium_Impl();
4217             LockOrigFileOnDemand( sal_False, sal_False );
4218             CreateTempFile( sal_True );
4219             GetMedium_Impl();
4220 
4221             if ( pImp->xStream.is() )
4222             {
4223                 try
4224                 {
4225                     uno::Reference< io::XTruncate > xTruncate( pImp->xStream, uno::UNO_QUERY_THROW );
4226                     if ( xTruncate.is() )
4227                         xTruncate->truncate();
4228 
4229                     xOptStorage->writeAndAttachToStream( pImp->xStream );
4230                     pImp->xStorage = xStorage;
4231                     bResult = sal_True;
4232                 }
4233                 catch( uno::Exception& )
4234                 {}
4235             }
4236 
4237             if ( !bResult )
4238             {
4239                 Close();
4240                 SetPhysicalName_Impl( String() );
4241                 SetName( aOrigURL );
4242                 GetMedium_Impl();
4243                 pImp->xStorage = xStorage;
4244             }
4245         }
4246     }
4247 
4248     return bResult;
4249 }
4250 
4251