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