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