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