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