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