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