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