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