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