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