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