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