xref: /AOO41X/main/sfx2/source/doc/docfile.cxx (revision 3edf699282957a8d2e0e344ed73ba96dfb5a45a4)
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 //------------------------------------------------------------------
TransactedTransferForFS_Impl(const INetURLObject & aSource,const INetURLObject & aDest,const Reference<::com::sun::star::ucb::XCommandEnvironment> & xComEnv)1794 sal_Bool SfxMedium::TransactedTransferForFS_Impl( const INetURLObject& aSource,
1795                                                 const INetURLObject& aDest,
1796                                                 const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
1797 {
1798     sal_Bool bResult = sal_False;
1799     Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
1800     Reference< XOutputStream > aDestStream;
1801     ::ucbhelper::Content aOriginalContent;
1802 
1803     try
1804     {
1805         aOriginalContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
1806     }
1807     catch ( ::com::sun::star::ucb::CommandAbortedException& )
1808     {
1809         eError = ERRCODE_ABORT;
1810     }
1811     catch ( ::com::sun::star::ucb::CommandFailedException& )
1812     {
1813         eError = ERRCODE_ABORT;
1814     }
1815     catch (const ::com::sun::star::ucb::ContentCreationException& ex)
1816     {
1817         eError = ERRCODE_IO_GENERAL;
1818         if (
1819             (ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER    ) ||
1820             (ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
1821            )
1822         {
1823             eError = ERRCODE_IO_NOTEXISTSPATH;
1824         }
1825     }
1826     catch (const ::com::sun::star::uno::Exception&)
1827     {
1828        eError = ERRCODE_IO_GENERAL;
1829     }
1830 
1831     if( !eError || (eError & ERRCODE_WARNING_MASK) )
1832     {
1833         if ( pImp->xStorage.is() )
1834             CloseStorage();
1835 
1836         CloseStreams_Impl();
1837 
1838         ::ucbhelper::Content aTempCont;
1839         if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aTempCont ) )
1840         {
1841             sal_Bool bTransactStarted = sal_False;
1842             SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
1843             SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
1844             sal_Bool bRename = pRename ? pRename->GetValue() : sal_False;
1845             sal_Bool bOverWrite = pOverWrite ? pOverWrite->GetValue() : !bRename;
1846 
1847             try
1848             {
1849                 if( bOverWrite && ::utl::UCBContentHelper::IsDocument( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) )
1850                 {
1851                     if( ! pImp->m_aBackupURL.getLength() )
1852                         DoInternalBackup_Impl( aOriginalContent );
1853 
1854                     if( pImp->m_aBackupURL.getLength() )
1855                     {
1856                         Reference< XInputStream > aTempInput = aTempCont.openStream();
1857                         bTransactStarted = sal_True;
1858                         aOriginalContent.setPropertyValue( ::rtl::OUString::createFromAscii( "Size" ),
1859                                                             uno::makeAny( (sal_Int64)0 ) );
1860                         aOriginalContent.writeStream( aTempInput, bOverWrite );
1861                         bResult = sal_True;
1862                     }
1863                     else
1864                     {
1865                         eError = ERRCODE_SFX_CANTCREATEBACKUP;
1866                     }
1867                 }
1868                 else
1869                 {
1870                     Reference< XInputStream > aTempInput = aTempCont.openStream();
1871                     aOriginalContent.writeStream( aTempInput, bOverWrite );
1872                     bResult = sal_True;
1873                 }
1874             }
1875             catch ( ::com::sun::star::ucb::CommandAbortedException& )
1876             {
1877                 eError = ERRCODE_ABORT;
1878             }
1879             catch ( ::com::sun::star::ucb::CommandFailedException& )
1880             {
1881                 eError = ERRCODE_ABORT;
1882             }
1883             catch ( ::com::sun::star::ucb::InteractiveIOException& r )
1884             {
1885                 if ( r.Code == IOErrorCode_ACCESS_DENIED )
1886                     eError = ERRCODE_IO_ACCESSDENIED;
1887                 else if ( r.Code == IOErrorCode_NOT_EXISTING )
1888                     eError = ERRCODE_IO_NOTEXISTS;
1889                 else if ( r.Code == IOErrorCode_CANT_READ )
1890                     eError = ERRCODE_IO_CANTREAD;
1891                 else
1892                     eError = ERRCODE_IO_GENERAL;
1893             }
1894             catch ( ::com::sun::star::uno::Exception& )
1895             {
1896                 eError = ERRCODE_IO_GENERAL;
1897             }
1898 
1899             if ( bResult )
1900             {
1901                 if ( pImp->pTempFile )
1902                 {
1903                     pImp->pTempFile->EnableKillingFile( sal_True );
1904                     delete pImp->pTempFile;
1905                     pImp->pTempFile = NULL;
1906                 }
1907             }
1908             else if ( bTransactStarted )
1909             {
1910                 UseBackupToRestore_Impl( aOriginalContent, xDummyEnv );
1911             }
1912         }
1913         else
1914             eError = ERRCODE_IO_CANTREAD;
1915     }
1916 
1917     return bResult;
1918 }
1919 
1920 //------------------------------------------------------------------
TryDirectTransfer(const::rtl::OUString & aURL,SfxItemSet & aTargetSet)1921 sal_Bool SfxMedium::TryDirectTransfer( const ::rtl::OUString& aURL, SfxItemSet& aTargetSet )
1922 {
1923     if ( GetError() )
1924         return sal_False;
1925 
1926     // if the document had no password it should be stored without password
1927     // if the document had password it should be stored with the same password
1928     // otherwise the stream copying can not be done
1929     SFX_ITEMSET_ARG( &aTargetSet, pNewPassItem, SfxStringItem, SID_PASSWORD, sal_False );
1930     SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem, SfxStringItem, SID_PASSWORD, sal_False );
1931     if ( ( !pNewPassItem && !pOldPassItem )
1932       || ( pNewPassItem && pOldPassItem && pNewPassItem->GetValue().Equals( pOldPassItem->GetValue() ) ) )
1933     {
1934         // the filter must be the same
1935         SFX_ITEMSET_ARG( &aTargetSet, pNewFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
1936         SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
1937         if ( pNewFilterItem && pOldFilterItem && pNewFilterItem->GetValue().Equals( pOldFilterItem->GetValue() ) )
1938         {
1939             // get the input stream and copy it
1940             // in case of success return true
1941             uno::Reference< io::XInputStream > xInStream = GetInputStream();
1942 
1943             ResetError();
1944             if ( xInStream.is() )
1945             {
1946                 try
1947                 {
1948                     uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
1949                     sal_Int64 nPos = 0;
1950                     if ( xSeek.is() )
1951                     {
1952                         nPos = xSeek->getPosition();
1953                         xSeek->seek( 0 );
1954                     }
1955 
1956                     uno::Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
1957                     ::ucbhelper::Content aTargetContent( aURL, xEnv );
1958 
1959                     InsertCommandArgument aInsertArg;
1960                     aInsertArg.Data = xInStream;
1961                     SFX_ITEMSET_ARG( &aTargetSet, pRename, SfxBoolItem, SID_RENAME, sal_False );
1962                     SFX_ITEMSET_ARG( &aTargetSet, pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
1963                     if ( (pOverWrite && !pOverWrite->GetValue()) // argument says: never overwrite
1964                       || (pRename && pRename->GetValue()) ) // argument says: rename file
1965                         aInsertArg.ReplaceExisting = sal_False;
1966                     else
1967                         aInsertArg.ReplaceExisting = sal_True; // default is overwrite existing files
1968 
1969                     Any aCmdArg;
1970                     aCmdArg <<= aInsertArg;
1971                     aTargetContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
1972                                                     aCmdArg );
1973 
1974                     if ( xSeek.is() )
1975                         xSeek->seek( nPos );
1976 
1977                     return sal_True;
1978                 }
1979                 catch( uno::Exception& )
1980                 {}
1981             }
1982         }
1983     }
1984 
1985     return sal_False;
1986 }
1987 
1988 //------------------------------------------------------------------
Transfer_Impl()1989 void SfxMedium::Transfer_Impl()
1990 {
1991     // The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
1992     String aNameURL;
1993     if ( pImp->pTempFile )
1994         aNameURL = pImp->pTempFile->GetURL();
1995     else if ( aLogicName.Len() && pImp->m_bSalvageMode )
1996     {
1997         // makes sence only in case logic name is set
1998         if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aNameURL ) )
1999             OSL_ENSURE( sal_False, "The medium name is not convertable!\n" );
2000     }
2001 
2002     if ( aNameURL.Len() && ( !eError || (eError & ERRCODE_WARNING_MASK) ) )
2003     {
2004         RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::Transfer_Impl, copying to target" );
2005 
2006         Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
2007         Reference< XOutputStream > rOutStream;
2008 
2009         // in case an output stream is provided from outside and the URL is correct
2010         // commit to the stream
2011         if( aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL )
2012         {
2013             // TODO/LATER: support storing to SID_STREAM
2014             SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
2015             if( pOutStreamItem && ( pOutStreamItem->GetValue() >>= rOutStream ) )
2016             {
2017                 if ( pImp->xStorage.is() )
2018                     CloseStorage();
2019 
2020                 CloseStreams_Impl();
2021 
2022                 INetURLObject aSource( aNameURL );
2023                 ::ucbhelper::Content aTempCont;
2024                 if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aTempCont ) )
2025                 {
2026                     try
2027                     {
2028                         sal_Int32 nRead;
2029                         sal_Int32 nBufferSize = 32767;
2030                         Sequence < sal_Int8 > aSequence ( nBufferSize );
2031                         Reference< XInputStream > aTempInput = aTempCont.openStream();
2032 
2033                         do
2034                         {
2035                             nRead = aTempInput->readBytes ( aSequence, nBufferSize );
2036                             if ( nRead < nBufferSize )
2037                             {
2038                                 Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
2039                                 rOutStream->writeBytes ( aTempBuf );
2040                             }
2041                             else
2042                                 rOutStream->writeBytes ( aSequence );
2043                         }
2044                         while ( nRead == nBufferSize );
2045 
2046                         // remove temporary file
2047                         if ( pImp->pTempFile )
2048                         {
2049                             pImp->pTempFile->EnableKillingFile( sal_True );
2050                             delete pImp->pTempFile;
2051                             pImp->pTempFile = NULL;
2052                         }
2053                     }
2054                     catch( Exception& )
2055                     {}
2056                 }
2057             }
2058             else
2059             {
2060                 DBG_ERROR( "Illegal Output stream parameter!\n" );
2061                 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
2062             }
2063 
2064             // free the reference
2065             if ( pSet )
2066                 pSet->ClearItem( SID_OUTPUTSTREAM );
2067 
2068             return;
2069         }
2070 
2071         GetContent();
2072         if ( !pImp->aContent.get().is() )
2073         {
2074             eError = ERRCODE_IO_NOTEXISTS;
2075             return;
2076         }
2077 
2078         SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize, SfxInt32Item, SID_SEGMENTSIZE, sal_False);
2079         if ( pSegmentSize )
2080         {
2081             // this file must be stored into a disk spanned package
2082             try
2083             {
2084                 uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetStorageFromURL( GetName(),
2085                         embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
2086 
2087                 // set segment size property; package will automatically be divided in pieces fitting
2088                 // into this size
2089                 ::com::sun::star::uno::Any aAny;
2090                 aAny <<= pSegmentSize->GetValue();
2091 
2092                 uno::Reference < beans::XPropertySet > xSet( pImp->xStorage, uno::UNO_QUERY );
2093                 xSet->setPropertyValue( String::CreateFromAscii("SegmentSize"), aAny );
2094 
2095                 // copy the temporary storage into the disk spanned package
2096                 GetStorage()->copyToStorage( xStor );
2097                 uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
2098                 if ( xTrans.is() )
2099                     xTrans->commit();
2100 
2101             }
2102             catch ( uno::Exception& )
2103             {
2104                 //TODO/MBA: error handling
2105             }
2106             return;
2107         }
2108 
2109         INetURLObject aDest( GetURLObject() );
2110 
2111         // source is the temp file written so far
2112         INetURLObject aSource( aNameURL );
2113 
2114         // a special case, an interaction handler should be used for
2115         // authentication in case it is available
2116         Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
2117         Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
2118         if (xInteractionHandler.is())
2119             xComEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler,
2120                                                       Reference< ::com::sun::star::ucb::XProgressHandler >() );
2121 
2122         if ( ::utl::LocalFileHelper::IsLocalFile( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) || !aDest.removeSegment() )
2123         {
2124             TransactedTransferForFS_Impl( aSource, aDest, xComEnv );
2125         }
2126         else
2127         {
2128             // create content for the parent folder and call transfer on that content with the source content
2129             // and the destination file name as parameters
2130             ::ucbhelper::Content aSourceContent;
2131             ::ucbhelper::Content aTransferContent;
2132 
2133             String aFileName = GetLongName();
2134             if ( !aFileName.Len() )
2135                 aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2136 
2137             try
2138             {
2139                 aTransferContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
2140             }
2141             catch (const ::com::sun::star::ucb::ContentCreationException& ex)
2142             {
2143                 eError = ERRCODE_IO_GENERAL;
2144                 if (
2145                     (ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER    ) ||
2146                     (ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
2147                    )
2148                 {
2149                     eError = ERRCODE_IO_NOTEXISTSPATH;
2150                 }
2151             }
2152             catch (const ::com::sun::star::uno::Exception&)
2153             {
2154                 eError = ERRCODE_IO_GENERAL;
2155             }
2156 
2157             if ( !eError || (eError & ERRCODE_WARNING_MASK) )
2158             {
2159                 // free resources, otherwise the transfer may fail
2160                 if ( pImp->xStorage.is() )
2161                     CloseStorage();
2162 
2163                 CloseStreams_Impl();
2164 
2165                 ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent );
2166 
2167                 // check for external parameters that may customize the handling of NameClash situations
2168                 SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
2169                 SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
2170                 sal_Int32 nNameClash;
2171                 if ( pOverWrite && !pOverWrite->GetValue() )
2172                     // argument says: never overwrite
2173                     nNameClash = NameClash::ERROR;
2174                 else if ( pRename && pRename->GetValue() )
2175                     // argument says: rename file
2176                     nNameClash = NameClash::RENAME;
2177                 else
2178                     // default is overwrite existing files
2179                     nNameClash = NameClash::OVERWRITE;
2180 
2181                 try
2182                 {
2183                     if (!aTransferContent.transferContent( aSourceContent, ::ucbhelper::InsertOperation_COPY, aFileName, nNameClash ))
2184                         eError = ERRCODE_IO_GENERAL;
2185                 }
2186                 catch ( ::com::sun::star::ucb::CommandAbortedException& )
2187                 {
2188                     eError = ERRCODE_ABORT;
2189                 }
2190                 catch ( ::com::sun::star::ucb::CommandFailedException& )
2191                 {
2192                     eError = ERRCODE_ABORT;
2193                 }
2194                 catch ( ::com::sun::star::ucb::InteractiveIOException& r )
2195                 {
2196                     if ( r.Code == IOErrorCode_ACCESS_DENIED )
2197                         eError = ERRCODE_IO_ACCESSDENIED;
2198                     else if ( r.Code == IOErrorCode_NOT_EXISTING )
2199                         eError = ERRCODE_IO_NOTEXISTS;
2200                     else if ( r.Code == IOErrorCode_CANT_READ )
2201                         eError = ERRCODE_IO_CANTREAD;
2202                     else
2203                         eError = ERRCODE_IO_GENERAL;
2204                 }
2205                 catch ( ::com::sun::star::uno::Exception& )
2206                 {
2207                     eError = ERRCODE_IO_GENERAL;
2208                 }
2209 
2210                 // do not switch from temporary file in case of nonfile protocol
2211             }
2212         }
2213 
2214         if ( ( !eError || (eError & ERRCODE_WARNING_MASK) ) && !pImp->pTempFile )
2215         {
2216             // without a TempFile the physical and logical name should be the same after successful transfer
2217             ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
2218                                                             aName );
2219             pImp->m_bSalvageMode = sal_False;
2220         }
2221     }
2222 }
2223 
2224 //------------------------------------------------------------------
DoInternalBackup_Impl(const::ucbhelper::Content & aOriginalContent,const String & aPrefix,const String & aExtension,const String & aDestDir)2225 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent,
2226                                        const String& aPrefix,
2227                                        const String& aExtension,
2228                                        const String& aDestDir )
2229 {
2230     RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoInternalBackup_Impl( with destdir )" );
2231 
2232     if ( pImp->m_aBackupURL.getLength() )
2233         return; // the backup was done already
2234 
2235     ::utl::TempFile aTransactTemp( aPrefix, &aExtension, &aDestDir );
2236     aTransactTemp.EnableKillingFile( sal_False );
2237 
2238     INetURLObject aBackObj( aTransactTemp.GetURL() );
2239     ::rtl::OUString aBackupName = aBackObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2240 
2241     Reference < ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
2242     ::ucbhelper::Content aBackupCont;
2243     if( ::ucbhelper::Content::create( aDestDir, xDummyEnv, aBackupCont ) )
2244     {
2245         try
2246         {
2247             if( aBackupCont.transferContent( aOriginalContent,
2248                                             ::ucbhelper::InsertOperation_COPY,
2249                                             aBackupName,
2250                                             NameClash::OVERWRITE ) )
2251             {
2252                 pImp->m_aBackupURL = aBackObj.GetMainURL( INetURLObject::NO_DECODE );
2253                 pImp->m_bRemoveBackup = sal_True;
2254             }
2255         }
2256         catch( Exception& )
2257         {}
2258     }
2259 
2260     if ( !pImp->m_aBackupURL.getLength() )
2261         aTransactTemp.EnableKillingFile( sal_True );
2262 }
2263 
2264 //------------------------------------------------------------------
DoInternalBackup_Impl(const::ucbhelper::Content & aOriginalContent)2265 void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent )
2266 {
2267     if ( pImp->m_aBackupURL.getLength() )
2268         return; // the backup was done already
2269 
2270     ::rtl::OUString aFileName =  GetURLObject().getName( INetURLObject::LAST_SEGMENT,
2271                                                         true,
2272                                                         INetURLObject::NO_DECODE );
2273 
2274     sal_Int32 nPrefixLen = aFileName.lastIndexOf( '.' );
2275     String aPrefix = ( nPrefixLen == -1 ) ? aFileName : aFileName.copy( 0, nPrefixLen );
2276     String aExtension = ( nPrefixLen == -1 ) ? String() : String(aFileName.copy( nPrefixLen ));
2277     String aBakDir = SvtPathOptions().GetBackupPath();
2278 
2279     DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aBakDir );
2280 
2281     if ( !pImp->m_aBackupURL.getLength() )
2282     {
2283         // the copiing to the backup catalog failed ( for example because
2284         // of using an encrypted partition as target catalog )
2285         // since the user did not specify to make backup explicitly
2286         // office should try to make backup in another place,
2287         // target catalog does not look bad for this case ( and looks
2288         // to be the only way for encrypted partitions )
2289 
2290         INetURLObject aDest = GetURLObject();
2291         if ( aDest.removeSegment() )
2292             DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aDest.GetMainURL( INetURLObject::NO_DECODE ) );
2293     }
2294 }
2295 
2296 
2297 //------------------------------------------------------------------
DoBackup_Impl()2298 void SfxMedium::DoBackup_Impl()
2299 {
2300     RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoBackup_Impl" );
2301 
2302     // source file name is the logical name of this medium
2303     INetURLObject aSource( GetURLObject() );
2304 
2305     // there is nothing to backup in case source file does not exist
2306     if ( !::utl::UCBContentHelper::IsDocument( aSource.GetMainURL( INetURLObject::NO_DECODE ) ) )
2307         return;
2308 
2309     sal_Bool        bSuccess = sal_False;
2310 
2311     // get path for backups
2312     String aBakDir = SvtPathOptions().GetBackupPath();
2313     if( aBakDir.Len() )
2314     {
2315         // create content for the parent folder ( = backup folder )
2316         ::ucbhelper::Content  aContent;
2317         Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
2318         if( ::ucbhelper::Content::create( aBakDir, xEnv, aContent ) )
2319         {
2320             // save as ".bak" file
2321             INetURLObject aDest( aBakDir );
2322             aDest.insertName( aSource.getName() );
2323             aDest.setExtension( DEFINE_CONST_UNICODE( "bak" ) );
2324             String aFileName = aDest.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2325 
2326             // create a content for the source file
2327             ::ucbhelper::Content aSourceContent;
2328             if ( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent ) )
2329             {
2330                 try
2331                 {
2332                     // do the transfer ( copy source file to backup dir )
2333                     bSuccess = aContent.transferContent( aSourceContent,
2334                                                         ::ucbhelper::InsertOperation_COPY,
2335                                                         aFileName,
2336                                                         NameClash::OVERWRITE );
2337                     if( bSuccess )
2338                     {
2339                         pImp->m_aBackupURL = aDest.GetMainURL( INetURLObject::NO_DECODE );
2340                         pImp->m_bRemoveBackup = sal_False;
2341                     }
2342                 }
2343                 catch ( ::com::sun::star::uno::Exception& )
2344                 {
2345                 }
2346             }
2347         }
2348     }
2349 
2350     if ( !bSuccess )
2351     {
2352         eError = ERRCODE_SFX_CANTCREATEBACKUP;
2353     }
2354 }
2355 
2356 //------------------------------------------------------------------
ClearBackup_Impl()2357 void SfxMedium::ClearBackup_Impl()
2358 {
2359     if( pImp->m_bRemoveBackup )
2360     {
2361         // currently a document is always stored in a new medium,
2362         // thus if a backup can not be removed the backup URL should not be cleaned
2363         if ( pImp->m_aBackupURL.getLength() )
2364         {
2365             if ( ::utl::UCBContentHelper::Kill( pImp->m_aBackupURL ) )
2366               // || !::utl::UCBContentHelper::IsDocument( pImp->m_aBackupURL ) );
2367             {
2368                 pImp->m_bRemoveBackup = sal_False;
2369                 pImp->m_aBackupURL = ::rtl::OUString();
2370             }
2371             else
2372             {
2373 
2374                 DBG_ERROR("Couldn't remove backup file!");
2375             }
2376         }
2377     }
2378     else
2379         pImp->m_aBackupURL = ::rtl::OUString();
2380 }
2381 
2382 //----------------------------------------------------------------
GetLockingStream_Impl()2383 void SfxMedium::GetLockingStream_Impl()
2384 {
2385     if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
2386       && !pImp->m_xLockingStream.is() )
2387     {
2388         SFX_ITEMSET_ARG( pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, sal_False);
2389         if ( pWriteStreamItem )
2390             pWriteStreamItem->GetValue() >>= pImp->m_xLockingStream;
2391 
2392         if ( !pImp->m_xLockingStream.is() )
2393         {
2394             // open the original document
2395             uno::Sequence< beans::PropertyValue > xProps;
2396             TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
2397             comphelper::MediaDescriptor aMedium( xProps );
2398 
2399             aMedium.addInputStreamOwnLock();
2400 
2401             uno::Reference< io::XInputStream > xInputStream;
2402             aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp->m_xLockingStream;
2403             aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
2404 
2405             if ( !pImp->pTempFile && !aName.Len() )
2406             {
2407                 // the medium is still based on the original file, it makes sence to initialize the streams
2408                 if ( pImp->m_xLockingStream.is() )
2409                     pImp->xStream = pImp->m_xLockingStream;
2410 
2411                 if ( xInputStream.is() )
2412                     pImp->xInputStream = xInputStream;
2413 
2414                 if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2415                     pImp->xInputStream = pImp->xStream->getInputStream();
2416             }
2417         }
2418     }
2419 }
2420 
2421 //----------------------------------------------------------------
GetMedium_Impl()2422 void SfxMedium::GetMedium_Impl()
2423 {
2424     if ( !pInStream )
2425     {
2426         pImp->bDownloadDone = sal_False;
2427         Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
2428 
2429         //TODO/MBA: need support for SID_STREAM
2430         SFX_ITEMSET_ARG( pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, sal_False);
2431         SFX_ITEMSET_ARG( pSet, pInStreamItem, SfxUnoAnyItem, SID_INPUTSTREAM, sal_False);
2432         if ( pWriteStreamItem )
2433         {
2434             pWriteStreamItem->GetValue() >>= pImp->xStream;
2435 
2436             if ( pInStreamItem )
2437                 pInStreamItem->GetValue() >>= pImp->xInputStream;
2438 
2439             if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2440                 pImp->xInputStream = pImp->xStream->getInputStream();
2441         }
2442         else if ( pInStreamItem )
2443         {
2444             pInStreamItem->GetValue() >>= pImp->xInputStream;
2445         }
2446         else
2447         {
2448             uno::Sequence < beans::PropertyValue > xProps;
2449             String aFileName;
2450             if ( aName.Len() )
2451             {
2452                 if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aFileName ) )
2453                 {
2454                     DBG_ERROR("Physical name not convertable!");
2455                 }
2456             }
2457             else
2458                 aFileName = GetName();
2459 
2460             // in case the temporary file exists the streams should be initialized from it,
2461             // but the original MediaDescriptor should not be changed
2462             sal_Bool bFromTempFile = ( pImp->pTempFile != NULL );
2463 
2464             if ( !bFromTempFile )
2465             {
2466                 GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, aFileName ) );
2467                 if( !(nStorOpenMode & STREAM_WRITE ) )
2468                     GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
2469                 if (xInteractionHandler.is())
2470                     GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER, makeAny(xInteractionHandler) ) );
2471             }
2472 
2473             if ( m_xInputStreamToLoadFrom.is() )
2474             {
2475                 pImp->xInputStream = m_xInputStreamToLoadFrom;
2476                 pImp->xInputStream->skipBytes(0);
2477                 if(m_bIsReadOnly)
2478                     GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
2479 
2480                 // m_xInputStreamToLoadFrom = 0;
2481             }
2482             else
2483             {
2484                 TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
2485                 comphelper::MediaDescriptor aMedium( xProps );
2486 
2487                 if ( pImp->m_xLockingStream.is() && !bFromTempFile )
2488                 {
2489                     // the medium is not based on the temporary file, so the original stream can be used
2490                     pImp->xStream = pImp->m_xLockingStream;
2491                 }
2492                 else
2493                 {
2494                     if ( bFromTempFile )
2495                     {
2496                         aMedium[comphelper::MediaDescriptor::PROP_URL()] <<= ::rtl::OUString( aFileName );
2497                         aMedium.erase( comphelper::MediaDescriptor::PROP_READONLY() );
2498                         aMedium.addInputStream();
2499                     }
2500                     else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
2501                     {
2502                         // use the special locking approach only for file URLs
2503                         aMedium.addInputStreamOwnLock();
2504                     }
2505                     else
2506                     {
2507                         //add acheck for protocol, to see if it's http or https then add
2508                         //the interecation handler to be used by the authentication dialog
2509                         ::rtl::OUString aScheme =  INetURLObject::GetScheme(GetURLObject().GetProtocol());
2510                         if( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) ||
2511                             aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) )
2512                         {
2513                             aMedium[comphelper::MediaDescriptor::PROP_AUTHENTICATIONHANDLER()] <<= GetAuthenticationInteractionHandler();
2514                         }
2515                         aMedium.addInputStream();
2516                     }
2517 
2518                     // the ReadOnly property set in aMedium is ignored
2519                     // the check is done in LockOrigFileOnDemand() for file and non-file URLs
2520 
2521                     //TODO/MBA: what happens if property is not there?!
2522                     aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp->xStream;
2523                     aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp->xInputStream;
2524                 }
2525 
2526                 GetContent();
2527                 if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2528                     pImp->xInputStream = pImp->xStream->getInputStream();
2529             }
2530 
2531             if ( !bFromTempFile )
2532             {
2533                 //TODO/MBA: need support for SID_STREAM
2534                 if ( pImp->xStream.is() )
2535                     GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM, makeAny( pImp->xStream ) ) );
2536 
2537                 GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM, makeAny( pImp->xInputStream ) ) );
2538             }
2539         }
2540 
2541         //TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
2542         if ( !GetError() && !pImp->xStream.is() && !pImp->xInputStream.is() )
2543         {
2544             SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
2545         }
2546 
2547         if ( !GetError() )
2548         {
2549             if ( pImp->xStream.is() )
2550             {
2551                 pInStream = utl::UcbStreamHelper::CreateStream( pImp->xStream );
2552             }
2553             else if ( pImp->xInputStream.is() )
2554             {
2555                 pInStream = utl::UcbStreamHelper::CreateStream( pImp->xInputStream );
2556             }
2557         }
2558 
2559         pImp->bDownloadDone = sal_True;
2560         pImp->aDoneLink.ClearPendingCall();
2561         pImp->aDoneLink.Call( (void*) GetError() );
2562     }
2563 }
2564 
2565 //----------------------------------------------------------------
IsRemote()2566 sal_Bool SfxMedium::IsRemote()
2567 {
2568     return bRemote;
2569 }
2570 
2571 //------------------------------------------------------------------
2572 
SetUpdatePickList(sal_Bool bVal)2573 void SfxMedium::SetUpdatePickList(sal_Bool bVal)
2574 {
2575     if(!pImp)
2576         pImp = new SfxMedium_Impl( this );
2577     pImp->bUpdatePickList = bVal;
2578 }
2579 //------------------------------------------------------------------
2580 
IsUpdatePickList() const2581 sal_Bool SfxMedium::IsUpdatePickList() const
2582 {
2583     return pImp? pImp->bUpdatePickList: sal_True;
2584 }
2585 //----------------------------------------------------------------
2586 
SetDoneLink(const Link & rLink)2587 void SfxMedium::SetDoneLink( const Link& rLink )
2588 {
2589     pImp->aDoneLink = rLink;
2590 }
2591 
2592 //----------------------------------------------------------------
2593 
SetDataAvailableLink(const Link & rLink)2594 void SfxMedium::SetDataAvailableLink( const Link& rLink )
2595 {
2596     pImp->aAvailableLink = rLink;
2597 }
2598 
2599 //----------------------------------------------------------------
StartDownload()2600 void SfxMedium::StartDownload()
2601 {
2602     GetInStream();
2603 }
2604 
DownLoad(const Link & aLink)2605 void SfxMedium::DownLoad( const Link& aLink )
2606 {
2607     SetDoneLink( aLink );
2608     GetInStream();
2609     if ( pInStream && !aLink.IsSet() )
2610     {
2611         while( !pImp->bDownloadDone )
2612             Application::Yield();
2613     }
2614 }
2615 
2616 //------------------------------------------------------------------
Init_Impl()2617 void SfxMedium::Init_Impl()
2618 /*  [Beschreibung]
2619     Setzt in den Logischen Namen eine gueltige ::com::sun::star::util::URL (Falls zuvor ein Filename
2620     drin war) und setzt den physikalschen Namen auf den Filenamen, falls
2621     vorhanden.
2622  */
2623 
2624 {
2625     Reference< XOutputStream > rOutStream;
2626 
2627     // TODO/LATER: handle lifetime of storages
2628     pImp->bDisposeStorage = sal_False;
2629 
2630     SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False);
2631     if ( pSalvageItem && !pSalvageItem->GetValue().Len() )
2632     {
2633         pSalvageItem = NULL;
2634         pSet->ClearItem( SID_DOC_SALVAGE );
2635     }
2636 
2637     if( aLogicName.Len() )
2638     {
2639         INetURLObject aUrl( aLogicName );
2640         INetProtocol eProt = aUrl.GetProtocol();
2641         if ( eProt == INET_PROT_NOT_VALID )
2642         {
2643             DBG_ERROR ( "Unknown protocol!" );
2644         }
2645         else
2646         {
2647             if ( aUrl.HasMark() )
2648             {
2649                 aLogicName = aUrl.GetURLNoMark( INetURLObject::NO_DECODE );
2650                 GetItemSet()->Put( SfxStringItem( SID_JUMPMARK, aUrl.GetMark() ) );
2651             }
2652 
2653             // try to convert the URL into a physical name - but never change a physical name
2654             // physical name may be set if the logical name is changed after construction
2655             if ( !aName.Len() )
2656                 ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aName );
2657             else {
2658                 DBG_ASSERT( pSalvageItem, "Suspicious change of logical name!" );
2659             }
2660         }
2661     }
2662 
2663     if ( pSalvageItem && pSalvageItem->GetValue().Len() )
2664     {
2665         aLogicName = pSalvageItem->GetValue();
2666         DELETEZ( pURLObj );
2667         pImp->m_bSalvageMode = sal_True;
2668     }
2669 
2670     // in case output stream is by mistake here
2671     // clear the reference
2672     SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
2673     if( pOutStreamItem
2674      && ( !( pOutStreamItem->GetValue() >>= rOutStream )
2675           || !aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL ) )
2676     {
2677         pSet->ClearItem( SID_OUTPUTSTREAM );
2678         DBG_ERROR( "Unexpected Output stream parameter!\n" );
2679     }
2680 
2681     if ( aLogicName.Len() )
2682     {
2683         // if the logic name is set it should be set in MediaDescriptor as well
2684         SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
2685         if ( !pFileNameItem )
2686         {
2687             // let the ItemSet be created if necessary
2688             GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, INetURLObject( aLogicName ).GetMainURL( INetURLObject::NO_DECODE ) ) );
2689         }
2690     }
2691 
2692     SetIsRemote_Impl();
2693 }
2694 
2695 //------------------------------------------------------------------
SfxMedium()2696 SfxMedium::SfxMedium()
2697 :   IMPL_CTOR( sal_False, 0 ),  // bRoot, pURLObj
2698 
2699     pFilter(0),
2700     pSet(0),
2701     pImp(new SfxMedium_Impl( this ))
2702 {
2703     Init_Impl();
2704 }
2705 //------------------------------------------------------------------
2706 
SfxMedium(const SfxMedium & rMedium,sal_Bool bTemporary)2707 SfxMedium::SfxMedium( const SfxMedium& rMedium, sal_Bool bTemporary )
2708 :   SvRefBase(),
2709     IMPL_CTOR( sal_True,    // bRoot, pURLObj
2710         rMedium.pURLObj ? new INetURLObject(*rMedium.pURLObj) : 0 ),
2711     pImp(new SfxMedium_Impl( this ))
2712 {
2713     bDirect       = rMedium.IsDirect();
2714     nStorOpenMode = rMedium.GetOpenMode();
2715     if ( !bTemporary )
2716         aName = rMedium.aName;
2717 
2718     pImp->bIsTemp = bTemporary;
2719     DBG_ASSERT( ! rMedium.pImp->bIsTemp, "Temporaeres Medium darf nicht kopiert werden" );
2720     aLogicName = rMedium.aLogicName;
2721     pSet =  rMedium.GetItemSet() ? new SfxItemSet(*rMedium.GetItemSet()) : 0;
2722     pFilter = rMedium.pFilter;
2723     Init_Impl();
2724     if( bTemporary )
2725         CreateTempFile( sal_True );
2726 }
2727 
2728 //------------------------------------------------------------------
2729 
UseInteractionHandler(sal_Bool bUse)2730 void SfxMedium::UseInteractionHandler( sal_Bool bUse )
2731 {
2732     pImp->bAllowDefaultIntHdl = bUse;
2733 }
2734 
2735 //------------------------------------------------------------------
2736 
2737 ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >
GetAuthenticationInteractionHandler()2738 SfxMedium::GetAuthenticationInteractionHandler()
2739 {
2740     // search a possible existing handler inside cached item set
2741     if ( pSet )
2742     {
2743         ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xHandler;
2744         SFX_ITEMSET_ARG( pSet, pHandler, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False);
2745         if ( pHandler && (pHandler->GetValue() >>= xHandler) && xHandler.is() )
2746             return xHandler;
2747     }
2748 
2749     // otherwhise return cached default handler ... if it exist.
2750     if ( pImp->xCredentialInteraction.is() )
2751         return pImp->xCredentialInteraction;
2752 
2753     // create default handler and cache it!
2754     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
2755     if ( xFactory.is() )
2756     {
2757         pImp->xCredentialInteraction = ::com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler >(
2758             xFactory->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), ::com::sun::star::uno::UNO_QUERY );
2759         return pImp->xCredentialInteraction;
2760     }
2761 
2762     return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2763 }
2764 
2765 //------------------------------------------------------------------
2766 
2767 ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >
GetInteractionHandler()2768 SfxMedium::GetInteractionHandler()
2769 {
2770     // if interaction isn't allowed explicitly ... return empty reference!
2771     if ( !pImp->bUseInteractionHandler )
2772         return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2773 
2774     // search a possible existing handler inside cached item set
2775     if ( pSet )
2776     {
2777         ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xHandler;
2778         SFX_ITEMSET_ARG( pSet, pHandler, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False);
2779         if ( pHandler && (pHandler->GetValue() >>= xHandler) && xHandler.is() )
2780             return xHandler;
2781     }
2782 
2783     // if default interaction isnt allowed explicitly ... return empty reference!
2784     if ( !pImp->bAllowDefaultIntHdl )
2785         return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2786 
2787     // otherwhise return cached default handler ... if it exist.
2788     if ( pImp->xInteraction.is() )
2789         return pImp->xInteraction;
2790 
2791     // create default handler and cache it!
2792     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
2793     if ( xFactory.is() )
2794     {
2795         pImp->xInteraction = ::com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler >(
2796             xFactory->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), ::com::sun::star::uno::UNO_QUERY );
2797         return pImp->xInteraction;
2798     }
2799 
2800     return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2801 }
2802 
2803 //----------------------------------------------------------------
2804 
SetFilter(const SfxFilter * pFilterP,sal_Bool)2805 void SfxMedium::SetFilter( const SfxFilter* pFilterP, sal_Bool /*bResetOrig*/ )
2806 {
2807     pFilter = pFilterP;
2808     pImp->nFileVersion = 0;
2809 }
2810 
2811 //----------------------------------------------------------------
2812 
GetOrigFilter(sal_Bool bNotCurrent) const2813 const SfxFilter* SfxMedium::GetOrigFilter( sal_Bool bNotCurrent ) const
2814 {
2815     return ( pImp->pOrigFilter || bNotCurrent ) ? pImp->pOrigFilter : pFilter;
2816 }
2817 
2818 //----------------------------------------------------------------
2819 
SetOrigFilter_Impl(const SfxFilter * pOrigFilter)2820 void SfxMedium::SetOrigFilter_Impl( const SfxFilter* pOrigFilter )
2821 {
2822     pImp->pOrigFilter = pOrigFilter;
2823 }
2824 
2825 //------------------------------------------------------------------
2826 
CreatePasswordToModifyHash(const::rtl::OUString & aPasswd,sal_Bool bWriter)2827 sal_uInt32 SfxMedium::CreatePasswordToModifyHash( const ::rtl::OUString& aPasswd, sal_Bool bWriter )
2828 {
2829     sal_uInt32 nHash = 0;
2830 
2831     if ( aPasswd.getLength() )
2832     {
2833         if ( bWriter )
2834         {
2835             nHash = ::comphelper::DocPasswordHelper::GetWordHashAsUINT32( aPasswd );
2836         }
2837         else
2838         {
2839             rtl_TextEncoding nEncoding = RTL_TEXTENCODING_UTF8;
2840 
2841             // if the MS-filter should be used
2842             // use the inconsistent algorithm to find the encoding specified by MS
2843             nEncoding = osl_getThreadTextEncoding();
2844             switch( nEncoding )
2845             {
2846                 case RTL_TEXTENCODING_ISO_8859_15:
2847                 case RTL_TEXTENCODING_MS_874:
2848                 case RTL_TEXTENCODING_MS_1250:
2849                 case RTL_TEXTENCODING_MS_1251:
2850                 case RTL_TEXTENCODING_MS_1252:
2851                 case RTL_TEXTENCODING_MS_1253:
2852                 case RTL_TEXTENCODING_MS_1254:
2853                 case RTL_TEXTENCODING_MS_1255:
2854                 case RTL_TEXTENCODING_MS_1256:
2855                 case RTL_TEXTENCODING_MS_1257:
2856                 case RTL_TEXTENCODING_MS_1258:
2857                 case RTL_TEXTENCODING_SHIFT_JIS:
2858                 case RTL_TEXTENCODING_GB_2312:
2859                 case RTL_TEXTENCODING_BIG5:
2860                     // in case the system uses an encoding from the list above, it should be used
2861                     break;
2862 
2863                 default:
2864                     // in case other encoding is used, use one of the encodings from the list
2865                     nEncoding = RTL_TEXTENCODING_MS_1250;
2866                     break;
2867             }
2868 
2869             nHash = ::comphelper::DocPasswordHelper::GetXLHashAsUINT16( aPasswd, nEncoding );
2870         }
2871     }
2872 
2873     return nHash;
2874 }
2875 
2876 //------------------------------------------------------------------
2877 
Close()2878 void SfxMedium::Close()
2879 {
2880     if ( pImp->xStorage.is() )
2881     {
2882         // don't close the streams if they belong to the
2883         // storage
2884         //TODO/MBA: how to?! Do we need the flag?!
2885         /*
2886         const SvStream *pStream = aStorage->GetSvStream();
2887         if ( pStream && pStream == pInStream )
2888         {
2889             CloseZipStorage_Impl();
2890             pInStream = NULL;
2891             pImp->xInputStream = Reference < XInputStream >();
2892             pImp->xLockBytes.Clear();
2893             if ( pSet )
2894                 pSet->ClearItem( SID_INPUTSTREAM );
2895             aStorage->SetDeleteStream( sal_True );
2896         }
2897         else if ( pStream && pStream == pOutStream )
2898         {
2899             pOutStream = NULL;
2900             aStorage->SetDeleteStream( sal_True );
2901         } */
2902 
2903         CloseStorage();
2904     }
2905 
2906     CloseStreams_Impl();
2907 
2908     UnlockFile( sal_False );
2909 }
2910 
CloseAndRelease()2911 void SfxMedium::CloseAndRelease()
2912 {
2913     if ( pImp->xStorage.is() )
2914     {
2915         // don't close the streams if they belong to the
2916         // storage
2917         //TODO/MBA: how to?! Do we need the flag?!
2918         /*
2919         const SvStream *pStream = aStorage->GetSvStream();
2920         if ( pStream && pStream == pInStream )
2921         {
2922             CloseZipStorage_Impl();
2923             pInStream = NULL;
2924             pImp->xInputStream = Reference < XInputStream >();
2925             pImp->xLockBytes.Clear();
2926             if ( pSet )
2927                 pSet->ClearItem( SID_INPUTSTREAM );
2928             aStorage->SetDeleteStream( sal_True );
2929         }
2930         else if ( pStream && pStream == pOutStream )
2931         {
2932             pOutStream = NULL;
2933             aStorage->SetDeleteStream( sal_True );
2934         } */
2935 
2936         CloseStorage();
2937     }
2938 
2939     CloseAndReleaseStreams_Impl();
2940 
2941     UnlockFile( sal_True );
2942 }
2943 
UnlockFile(sal_Bool bReleaseLockStream)2944 void SfxMedium::UnlockFile( sal_Bool bReleaseLockStream )
2945 {
2946     //->i126305
2947     //check if the file is local
2948     if ( ::utl::LocalFileHelper::IsLocalFile( aLogicName ) )
2949     {
2950     //<-i126305
2951         if ( pImp->m_xLockingStream.is() )
2952         {
2953             if ( bReleaseLockStream )
2954             {
2955                 try
2956                 {
2957                     uno::Reference< io::XInputStream > xInStream = pImp->m_xLockingStream->getInputStream();
2958                     uno::Reference< io::XOutputStream > xOutStream = pImp->m_xLockingStream->getOutputStream();
2959                     if ( xInStream.is() )
2960                         xInStream->closeInput();
2961                     if ( xOutStream.is() )
2962                         xOutStream->closeOutput();
2963                 }
2964                 catch( uno::Exception& )
2965                 {}
2966             }
2967 
2968             pImp->m_xLockingStream = uno::Reference< io::XStream >();
2969         }
2970 
2971         if ( pImp->m_bLocked )
2972         {
2973             try
2974             {
2975                 pImp->m_bLocked = sal_False;
2976                 ::svt::DocumentLockFile aLockFile( aLogicName );
2977                 // TODO/LATER: A warning could be shown in case the file is not the own one
2978                 aLockFile.RemoveFile();
2979             }
2980             catch( uno::Exception& )
2981             {}
2982         }
2983     //->i126305
2984     }
2985     else
2986     {
2987         //not local, check if webdav
2988         ::rtl::OUString aScheme =  INetURLObject::GetScheme(GetURLObject().GetProtocol());
2989         if( aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTP_SCHEME ) ||
2990             aScheme.equalsIgnoreAsciiCaseAscii( INET_HTTPS_SCHEME ) )
2991         {
2992             if ( pImp->m_bLocked )
2993             {
2994                 // an interaction handler should be used for authentication
2995                 try {
2996                     Reference< ::com::sun::star::task::XInteractionHandler > xHandler = GetAuthenticationInteractionHandler();
2997                     Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
2998                     xComEnv = new ::ucbhelper::CommandEnvironment( xHandler,
2999                                                                    Reference< ::com::sun::star::ucb::XProgressHandler >() );
3000                     ::ucbhelper::Content aContentToUnlock( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xComEnv);
3001                     pImp->m_bLocked = sal_False;
3002                     aContentToUnlock.unlock();
3003                 }
3004                 catch (ucb::InteractiveNetworkReadException& e)
3005                 {
3006                     //signalled when this resource can not be unlocked, for whatever reason
3007                 }
3008                 catch( uno::Exception& )
3009                 {}
3010             }
3011         }
3012     }
3013     //<-i126305
3014 }
3015 
CloseAndReleaseStreams_Impl()3016 void SfxMedium::CloseAndReleaseStreams_Impl()
3017 {
3018     CloseZipStorage_Impl();
3019 
3020     uno::Reference< io::XInputStream > xInToClose = pImp->xInputStream;
3021     uno::Reference< io::XOutputStream > xOutToClose;
3022     if ( pImp->xStream.is() )
3023     {
3024         xOutToClose = pImp->xStream->getOutputStream();
3025 
3026         // if the locking stream is closed here the related member should be cleaned
3027         if ( pImp->xStream == pImp->m_xLockingStream )
3028             pImp->m_xLockingStream = uno::Reference< io::XStream >();
3029     }
3030 
3031     // The probably exsisting SvStream wrappers should be closed first
3032     CloseStreams_Impl();
3033 
3034     // in case of salvage mode the storage is based on the streams
3035     if ( !pImp->m_bSalvageMode )
3036     {
3037         try
3038         {
3039             if ( xInToClose.is() )
3040                 xInToClose->closeInput();
3041             if ( xOutToClose.is() )
3042                 xOutToClose->closeOutput();
3043         }
3044         catch ( uno::Exception& )
3045         {
3046         }
3047     }
3048 }
3049 
3050 //------------------------------------------------------------------
CloseStreams_Impl()3051 void SfxMedium::CloseStreams_Impl()
3052 {
3053     CloseInStream_Impl();
3054     CloseOutStream_Impl();
3055 
3056     if ( pSet )
3057         pSet->ClearItem( SID_CONTENT );
3058 
3059     pImp->aContent = ::ucbhelper::Content();
3060 }
3061 
3062 //------------------------------------------------------------------
3063 
RefreshName_Impl()3064 void SfxMedium::RefreshName_Impl()
3065 {
3066 #if 0   //(dv)
3067     if ( pImp->aContent.get().is() )
3068     {
3069         String aNameP = pImp->xAnchor->GetViewURL();
3070         pImp->aOrigURL = aNameP;
3071         aLogicName = aNameP;
3072         DELETEZ( pURLObj );
3073         if (aLogicName.Len())
3074             aLogicName = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
3075         SetIsRemote_Impl();
3076     }
3077 #endif  //(dv)
3078 }
3079 
SetIsRemote_Impl()3080 void SfxMedium::SetIsRemote_Impl()
3081 {
3082     INetURLObject aObj( GetName() );
3083     switch( aObj.GetProtocol() )
3084     {
3085         case INET_PROT_FTP:
3086         case INET_PROT_HTTP:
3087         case INET_PROT_HTTPS:
3088         case INET_PROT_POP3:
3089         case INET_PROT_NEWS:
3090         case INET_PROT_IMAP:
3091 //        case INET_PROT_OUT:
3092         case INET_PROT_VIM:
3093             bRemote = sal_True; break;
3094         default:
3095             bRemote = ( GetName().CompareToAscii( "private:msgid", 13 ) == COMPARE_EQUAL );
3096             break;
3097     }
3098 
3099     // Da Dateien, die Remote geschrieben werden zur Uebertragung auch
3100     // gelesen werden koennen muessen
3101     if( bRemote )
3102         nStorOpenMode |= STREAM_READ;
3103 }
3104 
3105 
3106 
SetName(const String & aNameP,sal_Bool bSetOrigURL)3107 void SfxMedium::SetName( const String& aNameP, sal_Bool bSetOrigURL )
3108 {
3109     if( !pImp->aOrigURL.Len() )
3110         pImp->aOrigURL = aLogicName;
3111     if( bSetOrigURL )
3112         pImp->aOrigURL = aNameP;
3113     aLogicName = aNameP;
3114     DELETEZ( pURLObj );
3115     pImp->aContent = ::ucbhelper::Content();
3116     Init_Impl();
3117 }
3118 
3119 //----------------------------------------------------------------
GetOrigURL() const3120 const String& SfxMedium::GetOrigURL() const
3121 {
3122     return !pImp->aOrigURL.Len() ? (String &)aLogicName : pImp->aOrigURL;
3123 }
3124 
3125 //----------------------------------------------------------------
3126 
SetPhysicalName_Impl(const String & rNameP)3127 void SfxMedium::SetPhysicalName_Impl( const String& rNameP )
3128 {
3129     if ( rNameP != aName )
3130     {
3131         if( pImp->pTempFile )
3132         {
3133             delete pImp->pTempFile;
3134             pImp->pTempFile = NULL;
3135         }
3136 
3137         if ( aName.Len() || rNameP.Len() )
3138             pImp->aContent = ::ucbhelper::Content();
3139 
3140         aName = rNameP;
3141         bTriedStorage = sal_False;
3142         pImp->bIsStorage = sal_False;
3143     }
3144 }
3145 
3146 //------------------------------------------------------------------
SetTemporary(sal_Bool bTemp)3147 void SfxMedium::SetTemporary( sal_Bool bTemp )
3148 {
3149     pImp->bIsTemp = bTemp;
3150 }
3151 
3152 //------------------------------------------------------------------
IsTemporary() const3153 sal_Bool SfxMedium::IsTemporary() const
3154 {
3155     return pImp->bIsTemp;
3156 }
3157 
3158 //------------------------------------------------------------------
3159 
Exists(sal_Bool)3160 sal_Bool SfxMedium::Exists( sal_Bool /*bForceSession*/ )
3161 {
3162     DBG_ERROR( "Not implemented!" );
3163     return sal_True;
3164 }
3165 
3166 //------------------------------------------------------------------
3167 
ReOpen()3168 void SfxMedium::ReOpen()
3169 {
3170     sal_Bool bUseInteractionHandler = pImp->bUseInteractionHandler;
3171     pImp->bUseInteractionHandler = sal_False;
3172     GetMedium_Impl();
3173     pImp->bUseInteractionHandler = bUseInteractionHandler;
3174 }
3175 
3176 //------------------------------------------------------------------
3177 
CompleteReOpen()3178 void SfxMedium::CompleteReOpen()
3179 {
3180     // do not use temporary file for reopen and in case of success throw the temporary file away
3181     sal_Bool bUseInteractionHandler = pImp->bUseInteractionHandler;
3182     pImp->bUseInteractionHandler = sal_False;
3183 
3184     ::utl::TempFile* pTmpFile = NULL;
3185     if ( pImp->pTempFile )
3186     {
3187         pTmpFile = pImp->pTempFile;
3188         pImp->pTempFile = NULL;
3189         aName = String();
3190     }
3191 
3192     GetMedium_Impl();
3193 
3194     if ( GetError() )
3195     {
3196         if ( pImp->pTempFile )
3197         {
3198             pImp->pTempFile->EnableKillingFile( sal_True );
3199             delete pImp->pTempFile;
3200         }
3201         pImp->pTempFile = pTmpFile;
3202         if ( pImp->pTempFile )
3203             aName = pImp->pTempFile->GetFileName();
3204     }
3205     else
3206     {
3207         pTmpFile->EnableKillingFile( sal_True );
3208         delete pTmpFile;
3209 
3210     }
3211 
3212     pImp->bUseInteractionHandler = bUseInteractionHandler;
3213 }
3214 
3215 //------------------------------------------------------------------
SfxMedium(const String & rName,StreamMode nOpenMode,sal_Bool bDirectP,const SfxFilter * pFlt,SfxItemSet * pInSet)3216 SfxMedium::SfxMedium
3217 (
3218     const String &rName, StreamMode nOpenMode,  sal_Bool bDirectP,
3219     const SfxFilter *pFlt, SfxItemSet *pInSet
3220 )
3221 :   IMPL_CTOR( sal_False, 0 ),  // bRoot, pURLObj
3222     pFilter(pFlt),
3223     pSet( pInSet ),
3224     pImp(new SfxMedium_Impl( this ))
3225 {
3226     aLogicName = rName;
3227     nStorOpenMode = nOpenMode;
3228     bDirect = bDirectP;
3229     Init_Impl();
3230 }
3231 
3232 
SfxMedium(const::com::sun::star::uno::Sequence<::com::sun::star::beans::PropertyValue> & aArgs)3233 SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
3234     : IMPL_CTOR( sal_False, 0 ),  // bRoot, pURLObj
3235     pFilter(0),
3236     pSet(0),
3237     pImp(new SfxMedium_Impl( this ))
3238 {
3239     SfxAllItemSet *pParams = new SfxAllItemSet( SFX_APP()->GetPool() );
3240     pSet = pParams;
3241     TransformParameters( SID_OPENDOC, aArgs, *pParams );
3242 
3243     String aFilterName;
3244     SFX_ITEMSET_ARG( pSet, pFilterNameItem, SfxStringItem, SID_FILTER_NAME, sal_False );
3245     if( pFilterNameItem )
3246         aFilterName = pFilterNameItem->GetValue();
3247     pFilter = SFX_APP()->GetFilterMatcher().GetFilter4FilterName( aFilterName );
3248 
3249     sal_Bool bSalvage = sal_False;
3250     SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False );
3251     if( pSalvageItem )
3252     {
3253         // QUESTION: there is some treatment of Salvage in Init_Impl; align!
3254         bSalvage = sal_True;
3255         if ( pSalvageItem->GetValue().Len() )
3256         {
3257             // if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
3258             // that must be copied here
3259 
3260             SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
3261             if (!pFileNameItem) throw uno::RuntimeException();
3262             ::rtl::OUString aNewTempFileURL = SfxMedium::CreateTempCopyWithExt( pFileNameItem->GetValue() );
3263             if ( aNewTempFileURL.getLength() )
3264             {
3265                 pSet->Put( SfxStringItem( SID_FILE_NAME, aNewTempFileURL ) );
3266                 pSet->ClearItem( SID_INPUTSTREAM );
3267                 pSet->ClearItem( SID_STREAM );
3268                 pSet->ClearItem( SID_CONTENT );
3269             }
3270             else
3271             {
3272                 OSL_ENSURE( sal_False, "Can not create a new temporary file for crash recovery!\n" );
3273             }
3274         }
3275     }
3276 
3277     sal_Bool bReadOnly = sal_False;
3278     SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
3279     if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
3280         bReadOnly = sal_True;
3281 
3282     SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
3283     if (!pFileNameItem) throw uno::RuntimeException();
3284     aLogicName = pFileNameItem->GetValue();
3285     nStorOpenMode = bReadOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
3286     bDirect = sal_False;
3287     Init_Impl();
3288 }
3289 
3290 
3291 //------------------------------------------------------------------
3292 
SfxMedium(const uno::Reference<embed::XStorage> & rStor,const String & rBaseURL,const SfxItemSet * p,sal_Bool bRootP)3293 SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const String& rBaseURL, const SfxItemSet* p, sal_Bool bRootP )
3294 :   IMPL_CTOR( bRootP, 0 ), // bRoot, pURLObj
3295     pSet(0),
3296     pImp( new SfxMedium_Impl( this ))
3297 {
3298     String aType = SfxFilter::GetTypeFromStorage( rStor );
3299     pFilter = SFX_APP()->GetFilterMatcher().GetFilter4EA( aType );
3300     DBG_ASSERT( pFilter, "No Filter for storage found!" );
3301 
3302     Init_Impl();
3303     pImp->xStorage = rStor;
3304     pImp->bDisposeStorage = sal_False;
3305 
3306     // always take BaseURL first, could be overwritten by ItemSet
3307     GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
3308     if ( p )
3309         GetItemSet()->Put( *p );
3310 }
3311 
SfxMedium(const uno::Reference<embed::XStorage> & rStor,const String & rBaseURL,const String & rTypeName,const SfxItemSet * p,sal_Bool bRootP)3312 SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const String& rBaseURL, const String& rTypeName, const SfxItemSet* p, sal_Bool bRootP )
3313 :   IMPL_CTOR( bRootP, 0 ), // bRoot, pURLObj
3314     pSet(0),
3315     pImp( new SfxMedium_Impl( this ))
3316 {
3317     pFilter = SFX_APP()->GetFilterMatcher().GetFilter4EA( rTypeName );
3318     DBG_ASSERT( pFilter, "No Filter for storage found!" );
3319 
3320     Init_Impl();
3321     pImp->xStorage = rStor;
3322     pImp->bDisposeStorage = sal_False;
3323 
3324     // always take BaseURL first, could be overwritten by ItemSet
3325     GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
3326     if ( p )
3327         GetItemSet()->Put( *p );
3328 }
3329 
3330 //------------------------------------------------------------------
3331 
~SfxMedium()3332 SfxMedium::~SfxMedium()
3333 {
3334     /* Attention
3335         Don't enable CancelTransfers() till you know that the writer/web has changed his asynchronous load
3336         behaviour. Otherwhise may StyleSheets inside a html file will be loaded at the right time.
3337         => further the help will be empty then ... #100490#
3338      */
3339     //CancelTransfers();
3340 
3341     // if there is a requirement to clean the backup this is the last possibility to do it
3342     ClearBackup_Impl();
3343 
3344     Close();
3345 
3346     delete pSet;
3347 
3348     if( pImp->bIsTemp && aName.Len() )
3349     {
3350         String aTemp;
3351         if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aTemp ))
3352         {
3353             DBG_ERROR("Physical name not convertable!");
3354         }
3355 
3356         if ( !::utl::UCBContentHelper::Kill( aTemp ) )
3357         {
3358             DBG_ERROR("Couldn't remove temporary file!");
3359         }
3360     }
3361 
3362     pFilter = 0;
3363 
3364     delete pURLObj;
3365     delete pImp;
3366 }
3367 
3368 //------------------------------------------------------------------
SetItemSet(SfxItemSet * pNewSet)3369 void SfxMedium::SetItemSet(SfxItemSet *pNewSet)
3370 {
3371     delete pSet;
3372     pSet = pNewSet;
3373 }
3374 
3375 //----------------------------------------------------------------
GetURLObject() const3376 const INetURLObject& SfxMedium::GetURLObject() const
3377 {
3378     if( !pURLObj )
3379     {
3380         SfxMedium* pThis = const_cast < SfxMedium* > (this);
3381         pThis->pURLObj = new INetURLObject( aLogicName );
3382         if ( pThis->pURLObj->HasMark() )
3383             (*pThis->pURLObj) = INetURLObject( aLogicName ).GetURLNoMark();
3384     }
3385 
3386     return *pURLObj;
3387 }
3388 
3389 //----------------------------------------------------------------
3390 
GetPreRedirectedURL() const3391 const String& SfxMedium::GetPreRedirectedURL() const
3392 {
3393     return pImp->aPreRedirectionURL;
3394 }
3395 //----------------------------------------------------------------
3396 
GetMIMEAndRedirect(String &)3397 sal_uInt32 SfxMedium::GetMIMEAndRedirect( String& /*rName*/ )
3398 {
3399 /* dv !!!! not needed any longer ?
3400     INetProtocol eProt = GetURLObject().GetProtocol();
3401     if( eProt == INET_PROT_FTP && SvBinding::ShouldUseFtpProxy( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
3402     {
3403         Any aAny( UCB_Helper::GetProperty( GetContent(), WID_FLAG_IS_FOLDER ) );
3404         sal_Bool bIsFolder = sal_False;
3405         if ( ( aAny >>= bIsFolder ) && bIsFolder )
3406             return ERRCODE_NONE;
3407     }
3408 
3409     GetMedium_Impl();
3410     if( !eError && pImp->xBinding.Is() )
3411     {
3412         eError = pImp->xBinding->GetMimeType( rName );
3413 
3414         // Wir koennen keine Parameter wie CharSets usw.
3415         rName = rName.GetToken( 0, ';' );
3416         if( !eError )
3417         {
3418             if( !pImp->aPreRedirectionURL.Len() )
3419                 pImp->aPreRedirectionURL = aLogicName;
3420             SetName( pImp->xBinding->GetRedirectedURL() );
3421         }
3422         pImp->aExpireTime = pImp->xBinding->GetExpireDateTime();
3423     }
3424     return eError;
3425 */
3426     return 0;
3427 }
3428 
3429 //----------------------------------------------------------------
3430 
SetReferer(const String & rRefer)3431 void SfxMedium::SetReferer( const String& rRefer )
3432 {
3433     pImp->aReferer = rRefer;
3434 }
3435 //----------------------------------------------------------------
3436 
GetReferer() const3437 const String& SfxMedium::GetReferer( ) const
3438 {
3439     return pImp->aReferer;
3440 }
3441 
3442 //----------------------------------------------------------------
3443 
SetExpired_Impl(const DateTime & rDateTime)3444 void SfxMedium::SetExpired_Impl( const DateTime& rDateTime )
3445 {
3446     pImp->aExpireTime = rDateTime;
3447 }
3448 //----------------------------------------------------------------
3449 
IsExpired() const3450 sal_Bool SfxMedium::IsExpired() const
3451 {
3452     return pImp->aExpireTime.IsValid() && pImp->aExpireTime < DateTime();
3453 }
3454 //----------------------------------------------------------------
3455 
ForceSynchronStream_Impl(sal_Bool bForce)3456 void SfxMedium::ForceSynchronStream_Impl( sal_Bool bForce )
3457 {
3458     if( pInStream )
3459     {
3460         SvLockBytes* pBytes = pInStream->GetLockBytes();
3461         if( pBytes )
3462             pBytes->SetSynchronMode( bForce );
3463     }
3464     pImp->bForceSynchron = bForce;
3465 }
3466 
3467 //----------------------------------------------------------------
GetLoadTargetFrame() const3468 SfxFrame* SfxMedium::GetLoadTargetFrame() const
3469 {
3470     return pImp->wLoadTargetFrame;
3471 }
3472 //----------------------------------------------------------------
3473 
SetLoadTargetFrame(SfxFrame * pFrame)3474 void SfxMedium::SetLoadTargetFrame(SfxFrame* pFrame )
3475 {
3476     pImp->wLoadTargetFrame = pFrame;
3477 }
3478 //----------------------------------------------------------------
3479 
SetStorage_Impl(const uno::Reference<embed::XStorage> & rStor)3480 void SfxMedium::SetStorage_Impl( const uno::Reference < embed::XStorage >& rStor )
3481 {
3482     pImp->xStorage = rStor;
3483 }
3484 //----------------------------------------------------------------
3485 
GetItemSet() const3486 SfxItemSet* SfxMedium::GetItemSet() const
3487 {
3488     // this method *must* return an ItemSet, returning NULL can cause crashes
3489     if( !pSet )
3490         ((SfxMedium*)this)->pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
3491     return pSet;
3492 }
3493 //----------------------------------------------------------------
3494 
GetHeaderAttributes_Impl()3495 SvKeyValueIterator* SfxMedium::GetHeaderAttributes_Impl()
3496 {
3497     if( !pImp->xAttributes.Is() )
3498     {
3499         pImp->xAttributes = SvKeyValueIteratorRef( new SvKeyValueIterator );
3500 
3501         if ( GetContent().is() )
3502         {
3503             pImp->bIsCharsetInitialized = sal_True;
3504 
3505             try
3506             {
3507                 Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
3508                 ::rtl::OUString aContentType;
3509                 aAny >>= aContentType;
3510 
3511                 pImp->xAttributes->Append( SvKeyValue( ::rtl::OUString::createFromAscii( "content-type" ), aContentType ) );
3512             }
3513             catch ( ::com::sun::star::uno::Exception& )
3514             {
3515             }
3516         }
3517     }
3518 
3519     return pImp->xAttributes;
3520 }
3521 //----------------------------------------------------------------
3522 
GetHdl()3523 SvCompatWeakHdl* SfxMedium::GetHdl()
3524 {
3525     return pImp->GetHdl();
3526 }
3527 
IsDownloadDone_Impl()3528 sal_Bool SfxMedium::IsDownloadDone_Impl()
3529 {
3530     return pImp->bDownloadDone;
3531 }
3532 
GetInputStream()3533 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >  SfxMedium::GetInputStream()
3534 {
3535     if ( !pImp->xInputStream.is() )
3536         GetMedium_Impl();
3537     return pImp->xInputStream;
3538 }
3539 
GetVersionList(bool _bNoReload)3540 const uno::Sequence < util::RevisionTag >& SfxMedium::GetVersionList( bool _bNoReload )
3541 {
3542     // if the medium has no name, then this medium should represent a new document and can have no version info
3543     if ( ( !_bNoReload || !pImp->m_bVersionsAlreadyLoaded ) && !pImp->aVersions.getLength() &&
3544          ( aName.Len() || aLogicName.Len() ) && GetStorage().is() )
3545     {
3546         uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
3547                 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3548         if ( xReader.is() )
3549         {
3550             try
3551             {
3552                 pImp->aVersions = xReader->load( GetStorage() );
3553             }
3554             catch ( uno::Exception& )
3555             {
3556             }
3557         }
3558     }
3559 
3560     if ( !pImp->m_bVersionsAlreadyLoaded )
3561         pImp->m_bVersionsAlreadyLoaded = sal_True;
3562 
3563     return pImp->aVersions;
3564 }
3565 
GetVersionList(const uno::Reference<embed::XStorage> & xStorage)3566 uno::Sequence < util::RevisionTag > SfxMedium::GetVersionList( const uno::Reference < embed::XStorage >& xStorage )
3567 {
3568     uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
3569             ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3570     if ( xReader.is() )
3571     {
3572         try
3573         {
3574             return xReader->load( xStorage );
3575         }
3576         catch ( uno::Exception& )
3577         {
3578         }
3579     }
3580 
3581     return uno::Sequence < util::RevisionTag >();
3582 }
3583 
AddVersion_Impl(util::RevisionTag & rRevision)3584 sal_uInt16 SfxMedium::AddVersion_Impl( util::RevisionTag& rRevision )
3585 {
3586     if ( GetStorage().is() )
3587     {
3588         // Einen eindeutigen Namen f"ur den Stream ermitteln
3589         SvULongs aLongs;
3590         sal_Int32 nLength = pImp->aVersions.getLength();
3591         for ( sal_Int32 m=0; m<nLength; m++ )
3592         {
3593             sal_uInt32 nVer = (sal_uInt32) String( pImp->aVersions[m].Identifier ).Copy(7).ToInt32();
3594             sal_uInt16 n;
3595             for ( n=0; n<aLongs.Count(); n++ )
3596                 if ( nVer<aLongs[n] )
3597                     break;
3598 
3599             aLongs.Insert( nVer, n );
3600         }
3601 
3602         sal_uInt16 nKey;
3603         for ( nKey=0; nKey<aLongs.Count(); nKey++ )
3604             if ( aLongs[nKey] > ( sal_uIntPtr ) nKey+1 )
3605                 break;
3606 
3607         String aRevName = DEFINE_CONST_UNICODE( "Version" );
3608         aRevName += String::CreateFromInt32( nKey + 1 );
3609         pImp->aVersions.realloc( nLength+1 );
3610         rRevision.Identifier = aRevName;
3611         pImp->aVersions[nLength] = rRevision;
3612         return nKey;
3613     }
3614 
3615     return 0;
3616 }
3617 
RemoveVersion_Impl(const::rtl::OUString & rName)3618 sal_Bool SfxMedium::RemoveVersion_Impl( const ::rtl::OUString& rName )
3619 {
3620     if ( !pImp->aVersions.getLength() )
3621         return sal_False;
3622 
3623     sal_Int32 nLength = pImp->aVersions.getLength();
3624     for ( sal_Int32 n=0; n<nLength; n++ )
3625     {
3626         if ( pImp->aVersions[n].Identifier == rName )
3627         {
3628             for ( sal_Int32 m=n; m<nLength-1; m++ )
3629                 pImp->aVersions[m] = pImp->aVersions[m+1];
3630             pImp->aVersions.realloc(nLength-1);
3631             return sal_True;
3632         }
3633     }
3634 
3635     return sal_False;
3636 }
3637 
TransferVersionList_Impl(SfxMedium & rMedium)3638 sal_Bool SfxMedium::TransferVersionList_Impl( SfxMedium& rMedium )
3639 {
3640     if ( rMedium.pImp->aVersions.getLength() )
3641     {
3642         pImp->aVersions = rMedium.pImp->aVersions;
3643         return sal_True;
3644     }
3645 
3646     return sal_False;
3647 }
3648 
SaveVersionList_Impl(sal_Bool)3649 sal_Bool SfxMedium::SaveVersionList_Impl( sal_Bool /*bUseXML*/ )
3650 {
3651     if ( GetStorage().is() )
3652     {
3653         if ( !pImp->aVersions.getLength() )
3654             return sal_True;
3655 
3656         uno::Reference < document::XDocumentRevisionListPersistence > xWriter( comphelper::getProcessServiceFactory()->createInstance(
3657                 ::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
3658         if ( xWriter.is() )
3659         {
3660             try
3661             {
3662                 xWriter->store( GetStorage(), pImp->aVersions );
3663                 return sal_True;
3664             }
3665             catch ( uno::Exception& )
3666             {
3667             }
3668         }
3669     }
3670 
3671     return sal_False;
3672 }
3673 
3674 //----------------------------------------------------------------
IsReadOnly()3675 sal_Bool SfxMedium::IsReadOnly()
3676 {
3677     sal_Bool bReadOnly = sal_False;
3678 
3679     // a) ReadOnly filter cant produce read/write contents!
3680     bReadOnly = (
3681                     (pFilter                                                                         ) &&
3682                     ((pFilter->GetFilterFlags() & SFX_FILTER_OPENREADONLY) == SFX_FILTER_OPENREADONLY)
3683                 );
3684 
3685     // b) if filter allow read/write contents .. check open mode of the storage
3686     if (!bReadOnly)
3687         bReadOnly = !( GetOpenMode() & STREAM_WRITE );
3688 
3689     // c) the API can force the readonly state!
3690     if (!bReadOnly)
3691     {
3692         SFX_ITEMSET_ARG( GetItemSet(), pItem, SfxBoolItem, SID_DOC_READONLY, sal_False);
3693         if (pItem)
3694             bReadOnly = pItem->GetValue();
3695     }
3696 
3697     return bReadOnly;
3698 }
3699 
3700 //----------------------------------------------------------------
SetWritableForUserOnly(const::rtl::OUString & aURL)3701 sal_Bool SfxMedium::SetWritableForUserOnly( const ::rtl::OUString& aURL )
3702 {
3703     // UCB does not allow to allow write access only for the user,
3704     // use osl API
3705     sal_Bool bResult = sal_False;
3706 
3707     ::osl::DirectoryItem aDirItem;
3708     if ( ::osl::DirectoryItem::get( aURL, aDirItem ) == ::osl::FileBase::E_None )
3709     {
3710         ::osl::FileStatus aFileStatus( FileStatusMask_Attributes );
3711         if ( aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None
3712           && aFileStatus.isValid( FileStatusMask_Attributes ) )
3713         {
3714             sal_uInt64 nAttributes = aFileStatus.getAttributes();
3715 
3716             nAttributes &= ~(Attribute_OwnWrite |
3717                              Attribute_GrpWrite |
3718                              Attribute_OthWrite |
3719                              Attribute_ReadOnly);
3720             nAttributes |= Attribute_OwnWrite;
3721 
3722             bResult = ( osl::File::setAttributes( aURL, nAttributes ) == ::osl::FileBase::E_None );
3723         }
3724     }
3725 
3726     return bResult;
3727 }
3728 
3729 //----------------------------------------------------------------
CreateTempFile(sal_Bool bReplace)3730 void SfxMedium::CreateTempFile( sal_Bool bReplace )
3731 {
3732     if ( pImp->pTempFile )
3733     {
3734         if ( !bReplace )
3735             return;
3736 
3737         DELETEZ( pImp->pTempFile );
3738         aName = String();
3739     }
3740 
3741     do
3742     {
3743         pImp->pTempFile = new ::utl::TempFile();
3744         if ( GetName().Equals( pImp->pTempFile->GetURL() ) )
3745         {
3746             delete pImp->pTempFile;
3747             pImp->pTempFile = NULL;
3748         }
3749     } while ( pImp->pTempFile == NULL );
3750     pImp->pTempFile->EnableKillingFile( sal_True );
3751     aName = pImp->pTempFile->GetFileName();
3752     ::rtl::OUString aTmpURL = pImp->pTempFile->GetURL();
3753     if ( !aName.Len() || !aTmpURL.getLength() )
3754     {
3755         SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3756         return;
3757     }
3758 
3759     if ( !( nStorOpenMode & STREAM_TRUNC ) )
3760     {
3761         sal_Bool bTransferSuccess = sal_False;
3762 
3763         if ( GetContent().is()
3764           && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
3765           && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
3766         {
3767             // if there is already such a document, we should copy it
3768             // if it is a file system use OS copy process
3769             try
3770             {
3771                 uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
3772                 INetURLObject aTmpURLObj( aTmpURL );
3773                 ::rtl::OUString aFileName = aTmpURLObj.getName( INetURLObject::LAST_SEGMENT,
3774                                                                 true,
3775                                                                 INetURLObject::DECODE_WITH_CHARSET );
3776                 if ( aFileName.getLength() && aTmpURLObj.removeSegment() )
3777                 {
3778                     ::ucbhelper::Content aTargetContent( aTmpURLObj.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
3779                     if ( aTargetContent.transferContent( pImp->aContent, ::ucbhelper::InsertOperation_COPY, aFileName, NameClash::OVERWRITE ) )
3780                     {
3781                         SetWritableForUserOnly( aTmpURL );
3782                         bTransferSuccess = sal_True;
3783                     }
3784                 }
3785             }
3786             catch( uno::Exception& )
3787             {}
3788 
3789             if ( bTransferSuccess )
3790             {
3791                 CloseOutStream();
3792                 CloseInStream();
3793             }
3794         }
3795 
3796         if ( !bTransferSuccess && pInStream )
3797         {
3798             // the case when there is no URL-access available or this is a remote protocoll
3799             // but there is an input stream
3800             GetOutStream();
3801             if ( pOutStream )
3802             {
3803                 char        *pBuf = new char [8192];
3804                 sal_uInt32   nErr = ERRCODE_NONE;
3805 
3806                 pInStream->Seek(0);
3807                 pOutStream->Seek(0);
3808 
3809                 while( !pInStream->IsEof() && nErr == ERRCODE_NONE )
3810                 {
3811                     sal_uInt32 nRead = pInStream->Read( pBuf, 8192 );
3812                     nErr = pInStream->GetError();
3813                     pOutStream->Write( pBuf, nRead );
3814                 }
3815 
3816                 bTransferSuccess = sal_True;
3817                 delete[] pBuf;
3818                 CloseInStream();
3819             }
3820             CloseOutStream_Impl();
3821         }
3822         else
3823         {
3824             // Quite strange design, but currently it is expected that in this case no transfer happens
3825             // TODO/LATER: get rid of this inconsistent part of the call design
3826             bTransferSuccess = sal_True;
3827             CloseInStream();
3828         }
3829 
3830         if ( !bTransferSuccess )
3831         {
3832             SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3833             return;
3834         }
3835     }
3836 
3837     CloseStorage();
3838 }
3839 
3840 //----------------------------------------------------------------
CreateTempFileNoCopy()3841 void SfxMedium::CreateTempFileNoCopy()
3842 {
3843     // this call always replaces the existing temporary file
3844     if ( pImp->pTempFile )
3845     {
3846         delete pImp->pTempFile;
3847         pImp->pTempFile = NULL;
3848     }
3849 
3850     do
3851     {
3852         pImp->pTempFile = new ::utl::TempFile();
3853         if ( GetName().Equals( pImp->pTempFile->GetURL() ) )
3854         {
3855             delete pImp->pTempFile;
3856             pImp->pTempFile = NULL;
3857         }
3858     } while ( pImp->pTempFile == NULL );
3859     pImp->pTempFile->EnableKillingFile( sal_True );
3860     aName = pImp->pTempFile->GetFileName();
3861     if ( !aName.Len() )
3862     {
3863         SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3864         return;
3865     }
3866 
3867     CloseOutStream_Impl();
3868     CloseStorage();
3869 }
3870 
GetCharset()3871 ::rtl::OUString SfxMedium::GetCharset()
3872 {
3873     if( !pImp->bIsCharsetInitialized )
3874     {
3875         // Set an error in case there is no content?
3876         if ( GetContent().is() )
3877         {
3878             pImp->bIsCharsetInitialized = sal_True;
3879 
3880             try
3881             {
3882                 Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
3883                 ::rtl::OUString aField;
3884                 aAny >>= aField;
3885 
3886                 ::rtl::OString sContent = ::rtl::OUStringToOString( aField, RTL_TEXTENCODING_ASCII_US );
3887                 ByteString sType, sSubType;
3888                 INetContentTypeParameterList aParameters;
3889 
3890                 if( INetContentTypes::parse( sContent, sType, sSubType, &aParameters ) )
3891                 {
3892                     const INetContentTypeParameter * pCharset = aParameters.find("charset");
3893                     if (pCharset != 0)
3894                         pImp->aCharset = pCharset->m_sValue;
3895                 }
3896             }
3897             catch ( ::com::sun::star::uno::Exception& )
3898             {
3899             }
3900         }
3901     }
3902 
3903     return pImp->aCharset;
3904 }
3905 
SetCharset(::rtl::OUString aChs)3906 void SfxMedium::SetCharset( ::rtl::OUString aChs )
3907 {
3908     pImp->bIsCharsetInitialized = sal_True;
3909     pImp->aCharset = aChs;
3910 }
3911 
SignContents_Impl(sal_Bool bScriptingContent,const::rtl::OUString & aODFVersion,sal_Bool bHasValidDocumentSignature)3912 sal_Bool SfxMedium::SignContents_Impl( sal_Bool bScriptingContent, const ::rtl::OUString& aODFVersion, sal_Bool bHasValidDocumentSignature )
3913 {
3914     sal_Bool bChanges = sal_False;
3915 
3916     // the medium should be closed to be able to sign, the caller is responsible to close it
3917     if ( !IsOpen() && !GetError() )
3918     {
3919         // The component should know if there was a valid document signature, since
3920         // it should show a warning in this case
3921         uno::Sequence< uno::Any > aArgs( 2 );
3922         aArgs[0] <<= aODFVersion;
3923         aArgs[1] <<= bHasValidDocumentSignature;
3924         ::com::sun::star::uno::Reference< ::com::sun::star::security::XDocumentDigitalSignatures > xSigner(
3925             comphelper::getProcessServiceFactory()->createInstanceWithArguments(
3926                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ),
3927                 aArgs ),
3928             ::com::sun::star::uno::UNO_QUERY );
3929 
3930         if ( xSigner.is() )
3931         {
3932             uno::Reference< embed::XStorage > xWriteableZipStor;
3933             if ( !IsReadOnly() )
3934             {
3935                 // we can reuse the temporary file if there is one already
3936                 CreateTempFile( sal_False );
3937                 GetMedium_Impl();
3938 
3939                 try
3940                 {
3941                     if ( !pImp->xStream.is() )
3942                         throw uno::RuntimeException();
3943 
3944                     xWriteableZipStor = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING, pImp->xStream );
3945                     if ( !xWriteableZipStor.is() )
3946                         throw uno::RuntimeException();
3947 
3948                     uno::Reference< embed::XStorage > xMetaInf = xWriteableZipStor->openStorageElement(
3949                                                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
3950                                                     embed::ElementModes::READWRITE );
3951                     if ( !xMetaInf.is() )
3952                         throw uno::RuntimeException();
3953 
3954                     if ( bScriptingContent )
3955                     {
3956                         // If the signature has already the document signature it will be removed
3957                         // after the scripting signature is inserted.
3958                         uno::Reference< io::XStream > xStream(
3959                             xMetaInf->openStreamElement( xSigner->getScriptingContentSignatureDefaultStreamName(),
3960                                                          embed::ElementModes::READWRITE ),
3961                             uno::UNO_SET_THROW );
3962 
3963                         if ( xSigner->signScriptingContent( GetZipStorageToSign_Impl(), xStream ) )
3964                         {
3965                             // remove the document signature if any
3966                             ::rtl::OUString aDocSigName = xSigner->getDocumentContentSignatureDefaultStreamName();
3967                             if ( aDocSigName.getLength() && xMetaInf->hasByName( aDocSigName ) )
3968                                 xMetaInf->removeElement( aDocSigName );
3969 
3970                             uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
3971                             xTransact->commit();
3972                             xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
3973                             xTransact->commit();
3974 
3975                             // the temporary file has been written, commit it to the original file
3976                             Commit();
3977                             bChanges = sal_True;
3978                         }
3979                     }
3980                     else
3981                     {
3982                          uno::Reference< io::XStream > xStream(
3983                             xMetaInf->openStreamElement( xSigner->getDocumentContentSignatureDefaultStreamName(),
3984                                                          embed::ElementModes::READWRITE ),
3985                             uno::UNO_SET_THROW );
3986 
3987                         if ( xSigner->signDocumentContent( GetZipStorageToSign_Impl(), xStream ) )
3988                         {
3989                             uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
3990                             xTransact->commit();
3991                             xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
3992                             xTransact->commit();
3993 
3994                             // the temporary file has been written, commit it to the original file
3995                             Commit();
3996                             bChanges = sal_True;
3997                         }
3998                     }
3999                 }
4000                 catch ( uno::Exception& )
4001                 {
4002                     OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
4003                 }
4004 
4005                 CloseAndRelease();
4006             }
4007             else
4008             {
4009                 try
4010                 {
4011                     if ( bScriptingContent )
4012                         xSigner->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
4013                     else
4014                         xSigner->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
4015                 }
4016                 catch( uno::Exception& )
4017                 {
4018                     OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
4019                 }
4020             }
4021         }
4022 
4023         ResetError();
4024     }
4025 
4026     return bChanges;
4027 }
4028 
4029 //----------------------------------------------------------------
GetCachedSignatureState_Impl()4030 sal_uInt16 SfxMedium::GetCachedSignatureState_Impl()
4031 {
4032     return pImp->m_nSignatureState;
4033 }
4034 
4035 //----------------------------------------------------------------
SetCachedSignatureState_Impl(sal_uInt16 nState)4036 void SfxMedium::SetCachedSignatureState_Impl( sal_uInt16 nState )
4037 {
4038     pImp->m_nSignatureState = nState;
4039 }
4040 
HasStorage_Impl() const4041 sal_Bool SfxMedium::HasStorage_Impl() const
4042 {
4043     return pImp->xStorage.is();
4044 }
4045 
IsOpen() const4046 sal_Bool SfxMedium::IsOpen() const
4047 {
4048     return pInStream || pOutStream || pImp->xStorage.is();
4049 }
4050 
CreateTempCopyWithExt(const::rtl::OUString & aURL)4051 ::rtl::OUString SfxMedium::CreateTempCopyWithExt( const ::rtl::OUString& aURL )
4052 {
4053     ::rtl::OUString aResult;
4054 
4055     if ( aURL.getLength() )
4056     {
4057         sal_Int32 nPrefixLen = aURL.lastIndexOf( '.' );
4058         String aExt = ( nPrefixLen == -1 ) ? String() : String( aURL.copy( nPrefixLen ) );
4059 
4060         ::rtl::OUString aNewTempFileURL = ::utl::TempFile( String(), &aExt ).GetURL();
4061         if ( aNewTempFileURL.getLength() )
4062         {
4063             INetURLObject aSource( aURL );
4064             INetURLObject aDest( aNewTempFileURL );
4065             ::rtl::OUString aFileName = aDest.getName( INetURLObject::LAST_SEGMENT,
4066                                                         true,
4067                                                         INetURLObject::DECODE_WITH_CHARSET );
4068             if ( aFileName.getLength() && aDest.removeSegment() )
4069             {
4070                 try
4071                 {
4072                     uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
4073                     ::ucbhelper::Content aTargetContent( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
4074                     ::ucbhelper::Content aSourceContent( aSource.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
4075                     if ( aTargetContent.transferContent( aSourceContent,
4076                                                         ::ucbhelper::InsertOperation_COPY,
4077                                                         aFileName,
4078                                                         NameClash::OVERWRITE ) )
4079                     {
4080                         // Success
4081                         aResult = aNewTempFileURL;
4082                     }
4083                 }
4084                 catch( uno::Exception& )
4085                 {}
4086             }
4087         }
4088     }
4089 
4090     return aResult;
4091 }
4092 
CallApproveHandler(const uno::Reference<task::XInteractionHandler> & xHandler,uno::Any aRequest,sal_Bool bAllowAbort)4093 sal_Bool SfxMedium::CallApproveHandler( const uno::Reference< task::XInteractionHandler >& xHandler, uno::Any aRequest, sal_Bool bAllowAbort )
4094 {
4095     sal_Bool bResult = sal_False;
4096 
4097     if ( xHandler.is() )
4098     {
4099         try
4100         {
4101             uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( bAllowAbort ? 2 : 1 );
4102 
4103             ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove );
4104             aContinuations[ 0 ] = pApprove.get();
4105 
4106             if ( bAllowAbort )
4107             {
4108                 ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort( new ::comphelper::OInteractionAbort );
4109                 aContinuations[ 1 ] = pAbort.get();
4110             }
4111 
4112             xHandler->handle(::framework::InteractionRequest::CreateRequest (aRequest,aContinuations));
4113             bResult = pApprove->wasSelected();
4114         }
4115         catch( const Exception& )
4116         {
4117         }
4118     }
4119 
4120     return bResult;
4121 }
4122 
SwitchDocumentToTempFile()4123 ::rtl::OUString SfxMedium::SwitchDocumentToTempFile()
4124 {
4125     // the method returns empty string in case of failure
4126     ::rtl::OUString aResult;
4127     ::rtl::OUString aOrigURL = aLogicName;
4128 
4129     if ( aOrigURL.getLength() )
4130     {
4131         sal_Int32 nPrefixLen = aOrigURL.lastIndexOf( '.' );
4132         String aExt = ( nPrefixLen == -1 ) ? String() : String( aOrigURL.copy( nPrefixLen ) );
4133         ::rtl::OUString aNewURL = ::utl::TempFile( String(), &aExt ).GetURL();
4134 
4135         // TODO/LATER: In future the aLogicName should be set to shared folder URL
4136         //             and a temporary file should be created. Transport_Impl should be impossible then.
4137         if ( aNewURL.getLength() )
4138         {
4139             uno::Reference< embed::XStorage > xStorage = GetStorage();
4140             uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
4141 
4142             if ( xOptStorage.is() )
4143             {
4144                 // TODO/LATER: reuse the pImp->pTempFile if it already exists
4145                 CanDisposeStorage_Impl( sal_False );
4146                 Close();
4147                 SetPhysicalName_Impl( String() );
4148                 SetName( aNewURL );
4149 
4150                 // remove the readonly state
4151                 sal_Bool bWasReadonly = sal_False;
4152                 nStorOpenMode = SFX_STREAM_READWRITE;
4153                 SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
4154                 if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
4155                     bWasReadonly = sal_True;
4156                 GetItemSet()->ClearItem( SID_DOC_READONLY );
4157 
4158                 GetMedium_Impl();
4159                 LockOrigFileOnDemand( sal_False, sal_False );
4160                 CreateTempFile( sal_True );
4161                 GetMedium_Impl();
4162 
4163                 if ( pImp->xStream.is() )
4164                 {
4165                     try
4166                     {
4167                         xOptStorage->writeAndAttachToStream( pImp->xStream );
4168                         pImp->xStorage = xStorage;
4169                         aResult = aNewURL;
4170                     }
4171                     catch( uno::Exception& )
4172                     {}
4173                 }
4174 
4175                 if ( !aResult.getLength() )
4176                 {
4177                     Close();
4178                     SetPhysicalName_Impl( String() );
4179                     SetName( aOrigURL );
4180                     if ( bWasReadonly )
4181                     {
4182                         // set the readonly state back
4183                         nStorOpenMode = SFX_STREAM_READONLY;
4184                         GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY, sal_True));
4185                     }
4186                     GetMedium_Impl();
4187                     pImp->xStorage = xStorage;
4188                 }
4189             }
4190         }
4191     }
4192 
4193     return aResult;
4194 }
4195 
SwitchDocumentToFile(::rtl::OUString aURL)4196 sal_Bool SfxMedium::SwitchDocumentToFile( ::rtl::OUString aURL )
4197 {
4198     // the method is only for storage based documents
4199     sal_Bool bResult = sal_False;
4200     ::rtl::OUString aOrigURL = aLogicName;
4201 
4202     if ( aURL.getLength() && aOrigURL.getLength() )
4203     {
4204         uno::Reference< embed::XStorage > xStorage = GetStorage();
4205         uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
4206 
4207         if ( xOptStorage.is() )
4208         {
4209             // TODO/LATER: reuse the pImp->pTempFile if it already exists
4210             CanDisposeStorage_Impl( sal_False );
4211             Close();
4212             SetPhysicalName_Impl( String() );
4213             SetName( aURL );
4214 
4215             // open the temporary file based document
4216             GetMedium_Impl();
4217             LockOrigFileOnDemand( sal_False, sal_False );
4218             CreateTempFile( sal_True );
4219             GetMedium_Impl();
4220 
4221             if ( pImp->xStream.is() )
4222             {
4223                 try
4224                 {
4225                     uno::Reference< io::XTruncate > xTruncate( pImp->xStream, uno::UNO_QUERY_THROW );
4226                     if ( xTruncate.is() )
4227                         xTruncate->truncate();
4228 
4229                     xOptStorage->writeAndAttachToStream( pImp->xStream );
4230                     pImp->xStorage = xStorage;
4231                     bResult = sal_True;
4232                 }
4233                 catch( uno::Exception& )
4234                 {}
4235             }
4236 
4237             if ( !bResult )
4238             {
4239                 Close();
4240                 SetPhysicalName_Impl( String() );
4241                 SetName( aOrigURL );
4242                 GetMedium_Impl();
4243                 pImp->xStorage = xStorage;
4244             }
4245         }
4246     }
4247 
4248     return bResult;
4249 }
4250 
4251