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