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