1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sfx2.hxx" 30 31 #ifndef _MSGBOX_HXX //autogen 32 #include <vcl/msgbox.hxx> 33 #endif 34 #include <svl/eitem.hxx> 35 #include <svl/stritem.hxx> 36 #include <svl/intitem.hxx> 37 #include <tools/zcodec.hxx> 38 #include <com/sun/star/frame/XStorable.hpp> 39 #include <com/sun/star/frame/XModel.hpp> 40 #include <com/sun/star/frame/XFrame.hpp> 41 #include <com/sun/star/document/XFilter.hpp> 42 #include <com/sun/star/document/XImporter.hpp> 43 #include <com/sun/star/document/XExporter.hpp> 44 #include <com/sun/star/document/FilterOptionsRequest.hpp> 45 #include <com/sun/star/document/XInteractionFilterOptions.hpp> 46 #include <com/sun/star/task/XInteractionHandler.hpp> 47 #include <com/sun/star/task/XInteractionAskLater.hpp> 48 #include <com/sun/star/task/FutureDocumentVersionProductUpdateRequest.hpp> 49 #include <com/sun/star/task/InteractionClassification.hpp> 50 #include <com/sun/star/lang/XInitialization.hpp> 51 #include <com/sun/star/document/MacroExecMode.hpp> 52 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> 53 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> 54 #include <com/sun/star/ui/dialogs/XFilePicker.hpp> 55 #include <com/sun/star/beans/XPropertySetInfo.hpp> 56 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 57 #include <com/sun/star/beans/XPropertyAccess.hpp> 58 #include <com/sun/star/beans/PropertyValue.hpp> 59 #include <com/sun/star/beans/XPropertySet.hpp> 60 #include <com/sun/star/container/XNameAccess.hpp> 61 #include <com/sun/star/container/XSet.hpp> 62 #include <com/sun/star/embed/ElementModes.hpp> 63 #include <com/sun/star/embed/EmbedStates.hpp> 64 #include <com/sun/star/embed/Aspects.hpp> 65 #include <com/sun/star/embed/XTransactedObject.hpp> 66 #include <com/sun/star/embed/XEmbedPersist.hpp> 67 #include <com/sun/star/embed/XLinkageSupport.hpp> 68 #include <com/sun/star/embed/EntryInitModes.hpp> 69 #include <com/sun/star/embed/XOptimizedStorage.hpp> 70 #include <com/sun/star/embed/XEncryptionProtectedStorage.hpp> 71 #include <com/sun/star/io/XTruncate.hpp> 72 #include <com/sun/star/util/XModifiable.hpp> 73 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp> 74 #include <com/sun/star/xml/crypto/CipherID.hpp> 75 #include <com/sun/star/xml/crypto/DigestID.hpp> 76 77 #include <com/sun/star/document/XDocumentProperties.hpp> 78 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> 79 #include <comphelper/processfactory.hxx> 80 #include <comphelper/configurationhelper.hxx> 81 #include <comphelper/interaction.hxx> 82 #include <svtools/sfxecode.hxx> 83 #include <unotools/securityoptions.hxx> 84 #include <cppuhelper/weak.hxx> 85 #include <comphelper/processfactory.hxx> 86 #include <tools/cachestr.hxx> 87 #include <unotools/streamwrap.hxx> 88 89 #include <unotools/saveopt.hxx> 90 #include <unotools/useroptions.hxx> 91 #include <unotools/pathoptions.hxx> 92 #include <tools/urlobj.hxx> 93 #include <tools/diagnose_ex.h> 94 #include <unotools/localfilehelper.hxx> 95 #include <unotools/ucbhelper.hxx> 96 #include <unotools/tempfile.hxx> 97 #include <unotools/docinfohelper.hxx> 98 #include <ucbhelper/content.hxx> 99 #include <sot/storinfo.hxx> 100 #include <sot/exchange.hxx> 101 #include <sot/formats.hxx> 102 #include <comphelper/storagehelper.hxx> 103 #include <comphelper/seqstream.hxx> 104 #include <comphelper/documentconstants.hxx> 105 #include <comphelper/string.hxx> 106 #include <vcl/bitmapex.hxx> 107 #include <svtools/embedhlp.hxx> 108 #include <rtl/logfile.hxx> 109 #include <basic/modsizeexceeded.hxx> 110 #include <osl/file.hxx> 111 112 #include <sfx2/signaturestate.hxx> 113 #include <sfx2/app.hxx> 114 #include <sfx2/objsh.hxx> 115 #include <sfx2/childwin.hxx> 116 #include <sfx2/request.hxx> 117 #include "sfx2/sfxresid.hxx" 118 #include <sfx2/docfile.hxx> 119 #include "fltfnc.hxx" 120 #include <sfx2/docfilt.hxx> 121 #include <sfx2/docfac.hxx> 122 #include "objshimp.hxx" 123 #include "sfxtypes.hxx" 124 #include "doc.hrc" 125 #include <sfx2/sfxsids.hrc> 126 #include <sfx2/module.hxx> 127 #include <sfx2/dispatch.hxx> 128 #include "openflag.hxx" 129 #include "helper.hxx" 130 #include <sfx2/filedlghelper.hxx> 131 #include <sfx2/event.hxx> 132 #include "fltoptint.hxx" 133 #include <sfx2/viewfrm.hxx> 134 #include "graphhelp.hxx" 135 #include "appbaslib.hxx" 136 #include "appdata.hxx" 137 138 #ifdef OS2 139 #include <osl/file.hxx> 140 #include <stdio.h> 141 #include <sys/ea.h> 142 #endif 143 144 #include "../appl/app.hrc" 145 146 extern sal_uInt32 CheckPasswd_Impl( SfxObjectShell*, SfxItemPool&, SfxMedium* ); 147 148 using namespace ::com::sun::star; 149 using namespace ::com::sun::star::container; 150 using namespace ::com::sun::star::lang; 151 using namespace ::com::sun::star::ui::dialogs; 152 using namespace ::com::sun::star::uno; 153 using namespace ::com::sun::star::beans; 154 using namespace ::com::sun::star::ucb; 155 using namespace ::com::sun::star::task; 156 using namespace ::com::sun::star::document; 157 using namespace ::rtl; 158 using namespace ::cppu; 159 160 namespace css = ::com::sun::star; 161 162 //========================================================================= 163 void impl_addToModelCollection(const css::uno::Reference< css::frame::XModel >& xModel) 164 { 165 if (!xModel.is()) 166 return; 167 168 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); 169 css::uno::Reference< css::container::XSet > xModelCollection( 170 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.GlobalEventBroadcaster")), 171 css::uno::UNO_QUERY); 172 if (xModelCollection.is()) 173 { 174 try 175 { 176 xModelCollection->insert(css::uno::makeAny(xModel)); 177 } 178 catch ( uno::Exception& ) 179 { 180 OSL_ENSURE( sal_False, "The document seems to be in the collection already!\n" ); 181 } 182 } 183 } 184 185 //========================================================================= 186 187 sal_Bool SfxObjectShell::Save() 188 { 189 return SaveChildren(); 190 } 191 192 //-------------------------------------------------------------------------- 193 194 sal_Bool SfxObjectShell::SaveAs( SfxMedium& rMedium ) 195 { 196 return SaveAsChildren( rMedium ); 197 } 198 199 //------------------------------------------------------------------------- 200 201 sal_Bool SfxObjectShell::QuerySlotExecutable( sal_uInt16 /*nSlotId*/ ) 202 { 203 return sal_True; 204 } 205 206 //------------------------------------------------------------------------- 207 208 bool GetEncryptionData_Impl( const SfxItemSet* pSet, uno::Sequence< beans::NamedValue >& o_rEncryptionData ) 209 { 210 bool bResult = false; 211 if ( pSet ) 212 { 213 SFX_ITEMSET_ARG( pSet, pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False); 214 if ( pEncryptionDataItem ) 215 { 216 pEncryptionDataItem->GetValue() >>= o_rEncryptionData; 217 bResult = true; 218 } 219 else 220 { 221 SFX_ITEMSET_ARG( pSet, pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False); 222 if ( pPasswordItem ) 223 { 224 ::rtl::OUString aPassword = pPasswordItem->GetValue(); 225 o_rEncryptionData = ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPassword ); 226 bResult = true; 227 } 228 } 229 } 230 231 return bResult; 232 } 233 234 //------------------------------------------------------------------------- 235 sal_Bool SfxObjectShell::PutURLContentsToVersionStream_Impl( 236 ::rtl::OUString aURL, 237 const uno::Reference< embed::XStorage >& xDocStorage, 238 ::rtl::OUString aStreamName ) 239 { 240 sal_Bool bResult = sal_False; 241 try 242 { 243 uno::Reference< embed::XStorage > xVersion = xDocStorage->openStorageElement( 244 ::rtl::OUString::createFromAscii( "Versions" ), 245 embed::ElementModes::READWRITE ); 246 247 DBG_ASSERT( xVersion.is(), 248 "The method must throw an exception if the storage can not be opened!\n" ); 249 if ( !xVersion.is() ) 250 throw uno::RuntimeException(); 251 252 uno::Reference< io::XStream > xVerStream = xVersion->openStreamElement( 253 aStreamName, 254 embed::ElementModes::READWRITE ); 255 DBG_ASSERT( xVerStream.is(), "The method must throw an exception if the storage can not be opened!\n" ); 256 if ( !xVerStream.is() ) 257 throw uno::RuntimeException(); 258 259 uno::Reference< io::XOutputStream > xOutStream = xVerStream->getOutputStream(); 260 uno::Reference< io::XTruncate > xTrunc( xOutStream, uno::UNO_QUERY ); 261 262 DBG_ASSERT( xTrunc.is(), "The output stream must exist and implement XTruncate interface!\n" ); 263 if ( !xTrunc.is() ) 264 throw RuntimeException(); 265 266 uno::Reference< io::XInputStream > xTmpInStream = 267 ::comphelper::OStorageHelper::GetInputStreamFromURL( aURL ); 268 DBG_ASSERT( xTmpInStream.is(), "The method must create the stream or throw an exception!\n" ); 269 if ( !xTmpInStream.is() ) 270 throw uno::RuntimeException(); 271 272 xTrunc->truncate(); 273 ::comphelper::OStorageHelper::CopyInputToOutput( xTmpInStream, xOutStream ); 274 xOutStream->closeOutput(); 275 276 uno::Reference< embed::XTransactedObject > xTransact( xVersion, uno::UNO_QUERY ); 277 DBG_ASSERT( xTransact.is(), "The storage must implement XTransacted interface!\n" ); 278 if ( xTransact.is() ) 279 xTransact->commit(); 280 281 bResult = sal_True; 282 } 283 catch( uno::Exception& ) 284 { 285 // TODO/LATER: handle the error depending on exception 286 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 287 } 288 289 return bResult; 290 } 291 292 //------------------------------------------------------------------------- 293 ::rtl::OUString SfxObjectShell::CreateTempCopyOfStorage_Impl( const uno::Reference< embed::XStorage >& xStorage ) 294 { 295 ::rtl::OUString aTempURL = ::utl::TempFile().GetURL(); 296 297 DBG_ASSERT( aTempURL.getLength(), "Can't create a temporary file!\n" ); 298 if ( aTempURL.getLength() ) 299 { 300 try 301 { 302 uno::Reference< embed::XStorage > xTempStorage = 303 ::comphelper::OStorageHelper::GetStorageFromURL( aTempURL, embed::ElementModes::READWRITE ); 304 305 // the password will be transfered from the xStorage to xTempStorage by storage implemetation 306 xStorage->copyToStorage( xTempStorage ); 307 308 // the temporary storage was commited by the previous method and it will die by refcount 309 } 310 catch ( uno::Exception& ) 311 { 312 DBG_ERROR( "Creation of a storage copy is failed!" ); 313 ::utl::UCBContentHelper::Kill( aTempURL ); 314 315 aTempURL = ::rtl::OUString(); 316 317 // TODO/LATER: may need error code setting based on exception 318 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 319 } 320 } 321 322 return aTempURL; 323 } 324 325 //------------------------------------------------------------------------- 326 SvGlobalName SfxObjectShell::GetClassName() const 327 { 328 return GetFactory().GetClassId(); 329 } 330 331 //------------------------------------------------------------------------- 332 void SfxObjectShell::SetupStorage( const uno::Reference< embed::XStorage >& xStorage, 333 sal_Int32 nVersion, 334 sal_Bool bTemplate ) const 335 { 336 uno::Reference< beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY ); 337 338 if ( xProps.is() ) 339 { 340 SvGlobalName aName; 341 String aFullTypeName, aShortTypeName, aAppName; 342 sal_uInt32 nClipFormat=0; 343 344 FillClass( &aName, &nClipFormat, &aAppName, &aFullTypeName, &aShortTypeName, nVersion, bTemplate ); 345 if ( nClipFormat ) 346 { 347 // basic doesn't have a ClipFormat 348 // without MediaType the storage is not really usable, but currently the BasicIDE still 349 // is an SfxObjectShell and so we can't take this as an error 350 datatransfer::DataFlavor aDataFlavor; 351 SotExchange::GetFormatDataFlavor( nClipFormat, aDataFlavor ); 352 if ( aDataFlavor.MimeType.getLength() ) 353 { 354 try 355 { 356 xProps->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ), uno::makeAny( aDataFlavor.MimeType ) ); 357 } 358 catch( uno::Exception& ) 359 { 360 const_cast<SfxObjectShell*>( this )->SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 361 } 362 363 SvtSaveOptions aSaveOpt; 364 SvtSaveOptions::ODFDefaultVersion nDefVersion = aSaveOpt.GetODFDefaultVersion(); 365 366 uno::Sequence< beans::NamedValue > aEncryptionAlgs( 3 ); 367 aEncryptionAlgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StartKeyGenerationAlgorithm" ) ); 368 aEncryptionAlgs[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptionAlgorithm" ) ); 369 aEncryptionAlgs[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ChecksumAlgorithm" ) ); 370 // the default values, that should be used for ODF1.1 and older formats 371 aEncryptionAlgs[0].Value <<= xml::crypto::DigestID::SHA1; 372 aEncryptionAlgs[1].Value <<= xml::crypto::CipherID::BLOWFISH_CFB_8; 373 aEncryptionAlgs[2].Value <<= xml::crypto::DigestID::SHA1_1K; 374 375 if ( nDefVersion >= SvtSaveOptions::ODFVER_012 ) 376 { 377 try 378 { 379 // older versions can not have this property set, it exists only starting from ODF1.2 380 xProps->setPropertyValue( ::rtl::OUString::createFromAscii( "Version" ), uno::makeAny( ODFVER_012_TEXT ) ); 381 } 382 catch( uno::Exception& ) 383 { 384 } 385 386 if ( !aSaveOpt.IsUseSHA1InODF12() ) 387 { 388 aEncryptionAlgs[0].Value <<= xml::crypto::DigestID::SHA256; 389 aEncryptionAlgs[2].Value <<= xml::crypto::DigestID::SHA256_1K; 390 } 391 if ( !aSaveOpt.IsUseBlowfishInODF12() ) 392 aEncryptionAlgs[1].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; 393 } 394 395 try 396 { 397 // set the encryption algorithms accordingly; 398 // the setting does not trigger encryption, 399 // it just provides the format for the case that contents should be encrypted 400 uno::Reference< embed::XEncryptionProtectedStorage > xEncr( xStorage, uno::UNO_QUERY_THROW ); 401 xEncr->setEncryptionAlgorithms( aEncryptionAlgs ); 402 } 403 catch( uno::Exception& ) 404 { 405 const_cast<SfxObjectShell*>( this )->SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 406 } 407 408 } 409 } 410 } 411 } 412 413 //------------------------------------------------------------------------- 414 void SfxObjectShell::PrepareSecondTryLoad_Impl() 415 { 416 // only for internal use 417 pImp->m_xDocStorage = uno::Reference< embed::XStorage >(); 418 pImp->m_bIsInit = sal_False; 419 ResetError(); 420 } 421 422 //------------------------------------------------------------------------- 423 sal_Bool SfxObjectShell::GeneralInit_Impl( const uno::Reference< embed::XStorage >& xStorage, 424 sal_Bool bTypeMustBeSetAlready ) 425 { 426 if ( pImp->m_bIsInit ) 427 return sal_False; 428 429 pImp->m_bIsInit = sal_True; 430 if ( xStorage.is() ) 431 { 432 // no notification is required the storage is set the first time 433 pImp->m_xDocStorage = xStorage; 434 435 try { 436 uno::Reference < beans::XPropertySet > xPropSet( xStorage, uno::UNO_QUERY_THROW ); 437 Any a = xPropSet->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) ); 438 ::rtl::OUString aMediaType; 439 if ( !(a>>=aMediaType) || !aMediaType.getLength() ) 440 { 441 if ( bTypeMustBeSetAlready ) 442 { 443 SetError( ERRCODE_IO_BROKENPACKAGE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 444 return sal_False; 445 } 446 447 SetupStorage( xStorage, SOFFICE_FILEFORMAT_CURRENT, sal_False ); 448 } 449 } 450 catch ( uno::Exception& ) 451 { 452 OSL_ENSURE( sal_False, "Can't check storage's mediatype!\n" ); 453 } 454 } 455 else 456 pImp->m_bCreateTempStor = sal_True; 457 458 return sal_True; 459 } 460 461 //------------------------------------------------------------------------- 462 sal_Bool SfxObjectShell::InitNew( const uno::Reference< embed::XStorage >& xStorage ) 463 { 464 return GeneralInit_Impl( xStorage, sal_False ); 465 } 466 467 //------------------------------------------------------------------------- 468 sal_Bool SfxObjectShell::Load( SfxMedium& rMedium ) 469 { 470 return GeneralInit_Impl( rMedium.GetStorage(), sal_True ); 471 } 472 473 sal_Bool SfxObjectShell::DoInitNew( SfxMedium* pMed ) 474 /* [Beschreibung] 475 476 Diese von SvPersist geerbte virtuelle Methode wird gerufen, um 477 die SfxObjectShell-Instanz aus einem Storage (pStor != 0) bzw. 478 (pStor == 0) ganz neu zu initialisieren. 479 480 Wie alle Do...-Methoden liegt hier eine Steuerung vor, die eigentliche 481 Implementierung erfolgt, indem die ebenfalls virtuellen Methode 482 InitNew(SvStorate*) von der SfxObjectShell-Subclass implementiert wird. 483 484 F"ur pStor == 0 wird ein die SfxObjectShell-Instanz mit einem leeren 485 SfxMedium verbunden, sonst mit einem SfxMedium, welches auf den 486 als Parameter "ubergeben SvStorage verweist. 487 488 Erst nach InitNew() oder Load() ist das Objekt korrekt initialisiert. 489 490 [R"uckgabewert] 491 sal_True Das Objekt wurde initialisiert. 492 sal_False Das Objekt konnte nicht initialisiert werden 493 */ 494 495 { 496 ModifyBlocker_Impl aBlock( this ); 497 pMedium = pMed; 498 if ( !pMedium ) 499 { 500 bIsTmp = sal_True; 501 pMedium = new SfxMedium; 502 } 503 504 pMedium->CanDisposeStorage_Impl( sal_True ); 505 506 if ( InitNew( pMed ? pMed->GetStorage() : uno::Reference < embed::XStorage >() ) ) 507 { 508 // empty documents always get their macros from the user, so there is no reason to restrict access 509 pImp->aMacroMode.allowMacroExecution(); 510 if ( SFX_CREATE_MODE_EMBEDDED == eCreateMode ) 511 SetTitle( String( SfxResId( STR_NONAME ) )); 512 513 uno::Reference< frame::XModel > xModel ( GetModel(), uno::UNO_QUERY ); 514 if ( xModel.is() ) 515 { 516 SfxItemSet *pSet = GetMedium()->GetItemSet(); 517 uno::Sequence< beans::PropertyValue > aArgs; 518 TransformItems( SID_OPENDOC, *pSet, aArgs ); 519 sal_Int32 nLength = aArgs.getLength(); 520 aArgs.realloc( nLength + 1 ); 521 aArgs[nLength].Name = DEFINE_CONST_UNICODE("Title"); 522 aArgs[nLength].Value <<= ::rtl::OUString( GetTitle( SFX_TITLE_DETECT ) ); 523 xModel->attachResource( ::rtl::OUString(), aArgs ); 524 impl_addToModelCollection(xModel); 525 } 526 527 SetInitialized_Impl( true ); 528 return sal_True; 529 } 530 531 return sal_False; 532 } 533 534 //------------------------------------------------------------------------- 535 536 sal_Bool SfxObjectShell::ImportFromGeneratedStream_Impl( 537 const uno::Reference< io::XStream >& xStream, 538 const uno::Sequence< beans::PropertyValue >& aMediaDescr ) 539 { 540 if ( !xStream.is() ) 541 return sal_False; 542 543 if ( pMedium && pMedium->HasStorage_Impl() ) 544 pMedium->CloseStorage(); 545 546 sal_Bool bResult = sal_False; 547 548 try 549 { 550 uno::Reference< embed::XStorage > xStorage = 551 ::comphelper::OStorageHelper::GetStorageFromStream( xStream, embed::ElementModes::READWRITE ); 552 553 if ( !xStorage.is() ) 554 throw uno::RuntimeException(); 555 556 if ( !pMedium ) 557 pMedium = new SfxMedium( xStorage, String() ); 558 else 559 pMedium->SetStorage_Impl( xStorage ); 560 561 SfxAllItemSet aSet( SFX_APP()->GetPool() ); 562 TransformParameters( SID_OPENDOC, aMediaDescr, aSet ); 563 pMedium->GetItemSet()->Put( aSet ); 564 pMedium->CanDisposeStorage_Impl( sal_False ); 565 566 // allow the subfilter to reinit the model 567 if ( pImp->m_bIsInit ) 568 pImp->m_bIsInit = sal_False; 569 570 if ( LoadOwnFormat( *pMedium ) ) 571 { 572 bHasName = sal_True; 573 if ( !IsReadOnly() && IsLoadReadonly() ) 574 SetReadOnlyUI(); 575 576 bResult = sal_True; 577 OSL_ENSURE( pImp->m_xDocStorage == xStorage, "Wrong storage is used!\n" ); 578 } 579 580 // now the medium can be disconnected from the storage 581 // the medium is not allowed to dispose the storage so CloseStorage() can be used 582 pMedium->CloseStorage(); 583 } 584 catch( uno::Exception& ) 585 { 586 } 587 588 return bResult; 589 } 590 591 //------------------------------------------------------------------------- 592 593 sal_Bool SfxObjectShell::DoLoad( SfxMedium *pMed ) 594 { 595 ModifyBlocker_Impl aBlock( this ); 596 597 if ( SFX_CREATE_MODE_EMBEDDED != eCreateMode ) 598 GetpApp()->ShowStatusText( SfxResId(STR_DOC_LOADING) ); 599 600 pMedium = pMed; 601 pMedium->CanDisposeStorage_Impl( sal_True ); 602 603 sal_Bool bOk = sal_False; 604 const SfxFilter* pFilter = pMed->GetFilter(); 605 SfxItemSet* pSet = pMedium->GetItemSet(); 606 if( !pImp->nEventId ) 607 { 608 SFX_ITEMSET_ARG( 609 pSet, pTemplateItem, SfxBoolItem, 610 SID_TEMPLATE, sal_False); 611 SetActivateEvent_Impl( 612 ( pTemplateItem && pTemplateItem->GetValue() ) 613 ? SFX_EVENT_CREATEDOC : SFX_EVENT_OPENDOC ); 614 } 615 616 617 SFX_ITEMSET_ARG( pSet, pBaseItem, SfxStringItem, 618 SID_BASEURL, sal_False); 619 String aBaseURL; 620 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False); 621 if( pBaseItem ) 622 aBaseURL = pBaseItem->GetValue(); 623 else 624 { 625 if ( pSalvageItem ) 626 { 627 String aName( pMed->GetPhysicalName() ); 628 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aBaseURL ); 629 } 630 else 631 aBaseURL = pMed->GetBaseURL(); 632 } 633 pMed->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, aBaseURL ) ); 634 635 pImp->nLoadedFlags = 0; 636 pImp->bModelInitialized = sal_False; 637 638 //TODO/LATER: make a clear strategy how to handle "UsesStorage" etc. 639 sal_Bool bOwnStorageFormat = IsOwnStorageFormat_Impl( *pMedium ); 640 sal_Bool bHasStorage = IsPackageStorageFormat_Impl( *pMedium ); 641 if ( pMedium->GetFilter() ) 642 { 643 sal_uInt32 nError = HandleFilter( pMedium, this ); 644 if ( nError != ERRCODE_NONE ) 645 SetError( nError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 646 } 647 648 EnableSetModified( sal_False ); 649 650 pMedium->LockOrigFileOnDemand( sal_True, sal_False ); 651 if ( GetError() == ERRCODE_NONE && bOwnStorageFormat && ( !pFilter || !( pFilter->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) ) ) 652 { 653 uno::Reference< embed::XStorage > xStorage; 654 if ( pMedium->GetError() == ERRCODE_NONE ) 655 xStorage = pMedium->GetStorage(); 656 657 if( xStorage.is() && pMedium->GetLastStorageCreationState() == ERRCODE_NONE ) 658 { 659 DBG_ASSERT( pFilter, "No filter for storage found!" ); 660 661 try 662 { 663 sal_Bool bWarnMediaTypeFallback = sal_False; 664 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pRepairPackageItem, SfxBoolItem, SID_REPAIRPACKAGE, sal_False); 665 666 // treat the package as broken if the mediatype was retrieved as a fallback 667 uno::Reference< beans::XPropertySet > xStorProps( xStorage, uno::UNO_QUERY_THROW ); 668 xStorProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaTypeFallbackUsed" ) ) ) 669 >>= bWarnMediaTypeFallback; 670 671 if ( pRepairPackageItem && pRepairPackageItem->GetValue() ) 672 { 673 // the macros in repaired documents should be disabled 674 pMedium->GetItemSet()->Put( SfxUInt16Item( SID_MACROEXECMODE, document::MacroExecMode::NEVER_EXECUTE ) ); 675 676 // the mediatype was retrieved by using fallback solution but this is a repairing mode 677 // so it is acceptable to open the document if there is no contents that required manifest.xml 678 bWarnMediaTypeFallback = sal_False; 679 } 680 681 if ( bWarnMediaTypeFallback || !xStorage->getElementNames().getLength() ) 682 SetError( ERRCODE_IO_BROKENPACKAGE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 683 } 684 catch( uno::Exception& ) 685 { 686 // TODO/LATER: may need error code setting based on exception 687 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 688 } 689 690 // Load 691 if ( !GetError() ) 692 { 693 pImp->nLoadedFlags = 0; 694 pImp->bModelInitialized = sal_False; 695 bOk = xStorage.is() && LoadOwnFormat( *pMed ); 696 if ( bOk ) 697 { 698 // the document loaded from template has no name 699 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pTemplateItem, SfxBoolItem, SID_TEMPLATE, sal_False); 700 if ( !pTemplateItem || !pTemplateItem->GetValue() ) 701 bHasName = sal_True; 702 703 if ( !IsReadOnly() && IsLoadReadonly() ) 704 SetReadOnlyUI(); 705 } 706 else 707 SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 708 } 709 } 710 else 711 SetError( pMed->GetLastStorageCreationState(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 712 } 713 else if ( GetError() == ERRCODE_NONE && InitNew(0) ) 714 { 715 // Name vor ConvertFrom setzen, damit GetSbxObject() schon funktioniert 716 bHasName = sal_True; 717 SetName( SfxResId( STR_NONAME ) ); 718 719 if( !bHasStorage ) 720 pMedium->GetInStream(); 721 else 722 pMedium->GetStorage(); 723 724 if ( GetError() == ERRCODE_NONE ) 725 { 726 pImp->nLoadedFlags = 0; 727 pImp->bModelInitialized = sal_False; 728 if ( pMedium->GetFilter() && ( pMedium->GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) ) 729 { 730 uno::Reference < beans::XPropertySet > xSet( GetModel(), uno::UNO_QUERY ); 731 ::rtl::OUString sLockUpdates(::rtl::OUString::createFromAscii("LockUpdates")); 732 bool bSetProperty = true; 733 try 734 { 735 xSet->setPropertyValue( sLockUpdates, makeAny( (sal_Bool) sal_True ) ); 736 } 737 catch(const beans::UnknownPropertyException& ) 738 { 739 bSetProperty = false; 740 } 741 bOk = ImportFrom(*pMedium); 742 if(bSetProperty) 743 { 744 try 745 { 746 xSet->setPropertyValue( sLockUpdates, makeAny( (sal_Bool) sal_False ) ); 747 } 748 catch(const beans::UnknownPropertyException& ) 749 {} 750 } 751 UpdateLinks(); 752 FinishedLoading( SFX_LOADED_ALL ); 753 } 754 else 755 { 756 bOk = ConvertFrom(*pMedium); 757 InitOwnModel_Impl(); 758 } 759 } 760 } 761 762 if ( bOk ) 763 { 764 try 765 { 766 ::ucbhelper::Content aContent( pMedium->GetName(), com::sun::star::uno::Reference < XCommandEnvironment >() ); 767 com::sun::star::uno::Reference < XPropertySetInfo > xProps = aContent.getProperties(); 768 if ( xProps.is() ) 769 { 770 ::rtl::OUString aAuthor( RTL_CONSTASCII_USTRINGPARAM("Author") ); 771 ::rtl::OUString aKeywords( RTL_CONSTASCII_USTRINGPARAM("Keywords") ); 772 ::rtl::OUString aSubject( RTL_CONSTASCII_USTRINGPARAM("Subject") ); 773 Any aAny; 774 ::rtl::OUString aValue; 775 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( 776 GetModel(), uno::UNO_QUERY_THROW); 777 uno::Reference<document::XDocumentProperties> xDocProps 778 = xDPS->getDocumentProperties(); 779 if ( xProps->hasPropertyByName( aAuthor ) ) 780 { 781 aAny = aContent.getPropertyValue( aAuthor ); 782 if ( ( aAny >>= aValue ) ) 783 xDocProps->setAuthor(aValue); 784 } 785 if ( xProps->hasPropertyByName( aKeywords ) ) 786 { 787 aAny = aContent.getPropertyValue( aKeywords ); 788 if ( ( aAny >>= aValue ) ) 789 xDocProps->setKeywords( 790 ::comphelper::string::convertCommaSeparated(aValue)); 791 ; 792 } 793 if ( xProps->hasPropertyByName( aSubject ) ) 794 { 795 aAny = aContent.getPropertyValue( aSubject ); 796 if ( ( aAny >>= aValue ) ) { 797 xDocProps->setSubject(aValue); 798 } 799 } 800 } 801 } 802 catch( Exception& ) 803 { 804 } 805 806 // Falls nicht asynchron geladen wird selbst FinishedLoading aufrufen 807 if ( !( pImp->nLoadedFlags & SFX_LOADED_MAINDOCUMENT ) && 808 ( !pMedium->GetFilter() || pMedium->GetFilter()->UsesStorage() ) 809 ) 810 FinishedLoading( SFX_LOADED_MAINDOCUMENT ); 811 812 if( IsOwnStorageFormat_Impl(*pMed) && pMed->GetFilter() ) 813 { 814 //???? dv DirEntry aDirEntry( pMed->GetPhysicalName() ); 815 //???? dv SetFileName( aDirEntry.GetFull() ); 816 } 817 Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED) ); 818 819 if ( SFX_CREATE_MODE_EMBEDDED != eCreateMode ) 820 { 821 GetpApp()->HideStatusText(); 822 823 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pAsTempItem, SfxBoolItem, SID_TEMPLATE, sal_False); 824 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pPreviewItem, SfxBoolItem, SID_PREVIEW, sal_False); 825 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pHiddenItem, SfxBoolItem, SID_HIDDEN, sal_False); 826 if( bOk && pMedium->GetOrigURL().Len() 827 && !( pAsTempItem && pAsTempItem->GetValue() ) 828 && !( pPreviewItem && pPreviewItem->GetValue() ) 829 && !( pHiddenItem && pHiddenItem->GetValue() ) ) 830 { 831 INetURLObject aUrl( pMedium->GetOrigURL() ); 832 833 if ( aUrl.GetProtocol() == INET_PROT_FILE ) 834 { 835 const SfxFilter* pOrgFilter = pMedium->GetOrigFilter(); 836 Application::AddToRecentDocumentList( 837 aUrl.GetURLNoPass( INetURLObject::NO_DECODE ), 838 (pOrgFilter) ? pOrgFilter->GetMimeType() : String() ); 839 } 840 } 841 } 842 843 if ( pMedium->HasStorage_Impl() ) 844 { 845 uno::Reference< XInteractionHandler > xHandler( pMedium->GetInteractionHandler() ); 846 if ( xHandler.is() && !SFX_APP()->Get_Impl()->bODFVersionWarningLater ) 847 { 848 uno::Reference<beans::XPropertySet> xStorageProps( pMedium->GetStorage(), uno::UNO_QUERY_THROW ); 849 ::rtl::OUString sVersion; 850 try 851 { 852 xStorageProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ) >>= sVersion; 853 } 854 catch( const uno::Exception& ) 855 { 856 // Custom Property "ODFVersion" does not exist 857 } 858 859 if ( sVersion.getLength() ) 860 { 861 double nVersion = sVersion.toDouble(); 862 if ( nVersion > 1.20001 && SfxObjectShell_Impl::NeedsOfficeUpdateDialog() ) 863 // ODF version greater than 1.2 - added some decimal places to be safe against floating point conversion errors (hack) 864 { 865 ::rtl::OUString sDocumentURL( pMedium->GetOrigURL() ); 866 ::rtl::OUString aSystemFileURL; 867 if ( osl::FileBase::getSystemPathFromFileURL( sDocumentURL, aSystemFileURL ) == osl::FileBase::E_None ) 868 sDocumentURL = aSystemFileURL; 869 870 FutureDocumentVersionProductUpdateRequest aUpdateRequest; 871 aUpdateRequest.Classification = InteractionClassification_QUERY; 872 aUpdateRequest.DocumentURL = sDocumentURL; 873 874 ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest = new ::comphelper::OInteractionRequest( makeAny( aUpdateRequest ) ); 875 pRequest->addContinuation( new ::comphelper::OInteractionApprove ); 876 pRequest->addContinuation( new ::comphelper::OInteractionAbort ); 877 878 typedef ::comphelper::OInteraction< XInteractionAskLater > OInteractionAskLater; 879 OInteractionAskLater* pLater = new OInteractionAskLater; 880 pRequest->addContinuation( pLater ); 881 882 try 883 { 884 xHandler->handle( pRequest.get() ); 885 } 886 catch( const Exception& ) 887 { 888 DBG_UNHANDLED_EXCEPTION(); 889 } 890 if ( pLater->wasSelected() ) 891 SFX_APP()->Get_Impl()->bODFVersionWarningLater = true; 892 } 893 } 894 } 895 } 896 } 897 else 898 GetpApp()->HideStatusText(); 899 900 return bOk; 901 } 902 903 sal_uInt32 SfxObjectShell::HandleFilter( SfxMedium* pMedium, SfxObjectShell* pDoc ) 904 { 905 sal_uInt32 nError = ERRCODE_NONE; 906 SfxItemSet* pSet = pMedium->GetItemSet(); 907 SFX_ITEMSET_ARG( pSet, pOptions, SfxStringItem, SID_FILE_FILTEROPTIONS, sal_False ); 908 SFX_ITEMSET_ARG( pSet, pData, SfxUnoAnyItem, SID_FILTER_DATA, sal_False ); 909 if ( !pData && !pOptions ) 910 { 911 com::sun::star::uno::Reference< XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); 912 com::sun::star::uno::Reference< XNameAccess > xFilterCFG; 913 if( xServiceManager.is() ) 914 { 915 xFilterCFG = com::sun::star::uno::Reference< XNameAccess >( 916 xServiceManager->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), 917 UNO_QUERY ); 918 } 919 920 if( xFilterCFG.is() ) 921 { 922 sal_Bool bAbort = sal_False; 923 try { 924 const SfxFilter* pFilter = pMedium->GetFilter(); 925 Sequence < PropertyValue > aProps; 926 Any aAny = xFilterCFG->getByName( pFilter->GetName() ); 927 if ( aAny >>= aProps ) 928 { 929 sal_Int32 nPropertyCount = aProps.getLength(); 930 for( sal_Int32 nProperty=0; nProperty < nPropertyCount; ++nProperty ) 931 if( aProps[nProperty].Name.equals( ::rtl::OUString::createFromAscii("UIComponent")) ) 932 { 933 ::rtl::OUString aServiceName; 934 aProps[nProperty].Value >>= aServiceName; 935 if( aServiceName.getLength() ) 936 { 937 com::sun::star::uno::Reference< XInteractionHandler > rHandler = pMedium->GetInteractionHandler(); 938 if( rHandler.is() ) 939 { 940 // we need some properties in the media descriptor, so we have to make sure that they are in 941 Any aStreamAny; 942 aStreamAny <<= pMedium->GetInputStream(); 943 if ( pSet->GetItemState( SID_INPUTSTREAM ) < SFX_ITEM_SET ) 944 pSet->Put( SfxUnoAnyItem( SID_INPUTSTREAM, aStreamAny ) ); 945 if ( pSet->GetItemState( SID_FILE_NAME ) < SFX_ITEM_SET ) 946 pSet->Put( SfxStringItem( SID_FILE_NAME, pMedium->GetName() ) ); 947 if ( pSet->GetItemState( SID_FILTER_NAME ) < SFX_ITEM_SET ) 948 pSet->Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) ); 949 950 Sequence< PropertyValue > rProperties; 951 TransformItems( SID_OPENDOC, *pSet, rProperties, NULL ); 952 RequestFilterOptions* pFORequest = new RequestFilterOptions( pDoc->GetModel(), rProperties ); 953 954 com::sun::star::uno::Reference< XInteractionRequest > rRequest( pFORequest ); 955 rHandler->handle( rRequest ); 956 957 if ( !pFORequest->isAbort() ) 958 { 959 SfxAllItemSet aNewParams( pDoc->GetPool() ); 960 TransformParameters( SID_OPENDOC, 961 pFORequest->getFilterOptions(), 962 aNewParams, 963 NULL ); 964 965 SFX_ITEMSET_ARG( &aNewParams, 966 pFilterOptions, 967 SfxStringItem, 968 SID_FILE_FILTEROPTIONS, 969 sal_False ); 970 if ( pFilterOptions ) 971 pSet->Put( *pFilterOptions ); 972 973 SFX_ITEMSET_ARG( &aNewParams, 974 pFilterData, 975 SfxUnoAnyItem, 976 SID_FILTER_DATA, 977 sal_False ); 978 if ( pFilterData ) 979 pSet->Put( *pFilterData ); 980 } 981 else 982 bAbort = sal_True; 983 } 984 } 985 986 break; 987 } 988 } 989 990 if( bAbort ) 991 { 992 // filter options were not entered 993 nError = ERRCODE_ABORT; 994 } 995 } 996 catch( NoSuchElementException& ) 997 { 998 // the filter name is unknown 999 nError = ERRCODE_IO_INVALIDPARAMETER; 1000 } 1001 catch( Exception& ) 1002 { 1003 nError = ERRCODE_ABORT; 1004 } 1005 } 1006 } 1007 1008 return nError; 1009 } 1010 1011 //------------------------------------------------------------------------- 1012 1013 sal_Bool SfxObjectShell::IsOwnStorageFormat_Impl(const SfxMedium &rMedium) const 1014 { 1015 return !rMedium.GetFilter() || // Embedded 1016 ( rMedium.GetFilter()->IsOwnFormat() && 1017 rMedium.GetFilter()->UsesStorage() && 1018 rMedium.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60 ); 1019 } 1020 1021 //------------------------------------------------------------------------- 1022 1023 sal_Bool SfxObjectShell::IsPackageStorageFormat_Impl(const SfxMedium &rMedium) const 1024 { 1025 return !rMedium.GetFilter() || // Embedded 1026 ( rMedium.GetFilter()->UsesStorage() && 1027 rMedium.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60 ); 1028 } 1029 1030 //------------------------------------------------------------------------- 1031 1032 sal_Bool SfxObjectShell::DoSave() 1033 // DoSave wird nur noch ueber OLE aufgerufen. Sichern eigener Dokumente im SFX 1034 // laeuft uber DoSave_Impl, um das Anlegen von Backups zu ermoeglichen. 1035 // Save in eigenes Format jetzt auch wieder Hierueber 1036 { 1037 sal_Bool bOk = sal_False ; 1038 { 1039 ModifyBlocker_Impl aBlock( this ); 1040 1041 pImp->bIsSaving = sal_True; 1042 1043 uno::Sequence< beans::NamedValue > aEncryptionData; 1044 if ( IsPackageStorageFormat_Impl( *GetMedium() ) ) 1045 { 1046 if ( GetEncryptionData_Impl( GetMedium()->GetItemSet(), aEncryptionData ) ) 1047 { 1048 try 1049 { 1050 //TODO/MBA: GetOutputStorage?! Special mode, because it's "Save"?! 1051 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( GetMedium()->GetStorage(), aEncryptionData ); 1052 bOk = sal_True; 1053 } 1054 catch( uno::Exception& ) 1055 { 1056 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 1057 } 1058 1059 DBG_ASSERT( bOk, "The root storage must allow to set common password!\n" ); 1060 } 1061 else 1062 bOk = sal_True; 1063 1064 if ( HasBasic() ) 1065 { 1066 try 1067 { 1068 // The basic and dialogs related contents are still not able to proceed with save operation ( saveTo only ) 1069 // so since the document storage is locked a workaround has to be used 1070 1071 uno::Reference< embed::XStorage > xTmpStorage = ::comphelper::OStorageHelper::GetTemporaryStorage(); 1072 DBG_ASSERT( xTmpStorage.is(), "If a storage can not be created an exception must be thrown!\n" ); 1073 if ( !xTmpStorage.is() ) 1074 throw uno::RuntimeException(); 1075 1076 ::rtl::OUString aBasicStorageName( RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ); 1077 ::rtl::OUString aDialogsStorageName( RTL_CONSTASCII_USTRINGPARAM( "Dialogs" ) ); 1078 if ( GetMedium()->GetStorage()->hasByName( aBasicStorageName ) ) 1079 GetMedium()->GetStorage()->copyElementTo( aBasicStorageName, xTmpStorage, aBasicStorageName ); 1080 if ( GetMedium()->GetStorage()->hasByName( aDialogsStorageName ) ) 1081 GetMedium()->GetStorage()->copyElementTo( aDialogsStorageName, xTmpStorage, aDialogsStorageName ); 1082 1083 GetBasicManager(); 1084 1085 // disconnect from the current storage 1086 pImp->pBasicManager->setStorage( xTmpStorage ); 1087 1088 // store to the current storage 1089 pImp->pBasicManager->storeLibrariesToStorage( GetMedium()->GetStorage() ); 1090 1091 // connect to the current storage back 1092 pImp->pBasicManager->setStorage( GetMedium()->GetStorage() ); 1093 } 1094 catch( uno::Exception& ) 1095 { 1096 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 1097 bOk = sal_False; 1098 } 1099 } 1100 } 1101 1102 if ( bOk ) 1103 bOk = Save(); 1104 1105 bOk = pMedium->Commit(); 1106 } 1107 1108 //#88046 1109 // if ( bOk ) 1110 // SetModified( sal_False ); 1111 return bOk; 1112 } 1113 1114 void Lock_Impl( SfxObjectShell* pDoc, sal_Bool bLock ) 1115 { 1116 SfxViewFrame *pFrame= SfxViewFrame::GetFirst( pDoc ); 1117 while ( pFrame ) 1118 { 1119 pFrame->GetDispatcher()->Lock( bLock ); 1120 pFrame->Enable( !bLock ); 1121 pFrame = SfxViewFrame::GetNext( *pFrame, pDoc ); 1122 } 1123 1124 } 1125 1126 //------------------------------------------------------------------------- 1127 1128 sal_Bool SfxObjectShell::SaveTo_Impl 1129 ( 1130 SfxMedium &rMedium, // Medium, in das gespeichert werden soll 1131 const SfxItemSet* pSet 1132 ) 1133 1134 /* [Beschreibung] 1135 1136 Schreibt den aktuellen Inhalt in das Medium rMedium. 1137 Ist das Zielmedium kein Storage, so wird ueber ein temporaeres 1138 Medium gespeichert, sonst direkt, da das Medium transacted 1139 geschaltet ist, wenn wir es selbst geoeffnet haben und falls wir 1140 Server sind entweder der Container einen transacted Storage zur 1141 Verfuegung stellt oder selbst einen temporaeren Storage erzeugt hat. 1142 */ 1143 1144 { 1145 RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "PERFORMANCE SfxObjectShell::SaveTo_Impl" ); 1146 if( RTL_LOGFILE_HASLOGFILE() ) 1147 { 1148 ByteString aString( rMedium.GetName(), RTL_TEXTENCODING_ASCII_US ); 1149 RTL_LOGFILE_PRODUCT_CONTEXT_TRACE1( aLog, "saving \"%s\"", aString.GetBuffer() ); 1150 } 1151 1152 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Begin" ) ) ); 1153 1154 ModifyBlocker_Impl aMod(this); 1155 1156 const SfxFilter *pFilter = rMedium.GetFilter(); 1157 if ( !pFilter ) 1158 { 1159 // if no filter was set, use the default filter 1160 // this should be changed in the feature, it should be an error! 1161 DBG_ERROR("No filter set!"); 1162 pFilter = GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_IMPORT | SFX_FILTER_EXPORT ); 1163 rMedium.SetFilter(pFilter); 1164 } 1165 1166 sal_Bool bStorageBasedSource = IsPackageStorageFormat_Impl( *pMedium ); 1167 sal_Bool bStorageBasedTarget = IsPackageStorageFormat_Impl( rMedium ); 1168 sal_Bool bOwnSource = IsOwnStorageFormat_Impl( *pMedium ); 1169 sal_Bool bOwnTarget = IsOwnStorageFormat_Impl( rMedium ); 1170 1171 // Examine target format to determine whether to query if any password 1172 // protected libraries exceed the size we can handler 1173 if ( bOwnTarget && !QuerySaveSizeExceededModules_Impl( rMedium.GetInteractionHandler() ) ) 1174 { 1175 SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 1176 return sal_False; 1177 } 1178 1179 sal_Bool bNeedsDisconnectionOnFail = sal_False; 1180 1181 sal_Bool bStoreToSameLocation = sal_False; 1182 1183 // the detection whether the script is changed should be done before saving 1184 sal_Bool bTryToPreserveScriptSignature = sal_False; 1185 // no way to detect whether a filter is oasis format, have to wait for saving process 1186 sal_Bool bNoPreserveForOasis = sal_False; 1187 if ( bOwnSource && bOwnTarget 1188 && ( pImp->nScriptingSignatureState == SIGNATURESTATE_SIGNATURES_OK 1189 || pImp->nScriptingSignatureState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED 1190 || pImp->nScriptingSignatureState == SIGNATURESTATE_SIGNATURES_INVALID ) ) 1191 { 1192 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "MacroSignaturePreserving" ) ) ); 1193 1194 // the checking of the library modified state iterates over the libraries, should be done only when required 1195 // currently the check is commented out since it is broken, we have to check the signature every time we save 1196 // TODO/LATER: let isAnyContainerModified() work! 1197 bTryToPreserveScriptSignature = sal_True; // !pImp->pBasicManager->isAnyContainerModified(); 1198 if ( bTryToPreserveScriptSignature ) 1199 { 1200 // check that the storage format stays the same 1201 SvtSaveOptions aSaveOpt; 1202 SvtSaveOptions::ODFDefaultVersion nVersion = aSaveOpt.GetODFDefaultVersion(); 1203 1204 ::rtl::OUString aODFVersion; 1205 try 1206 { 1207 uno::Reference < beans::XPropertySet > xPropSet( GetStorage(), uno::UNO_QUERY_THROW ); 1208 xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ) >>= aODFVersion; 1209 } 1210 catch( uno::Exception& ) 1211 {} 1212 1213 // preserve only if the same filter has been used 1214 bTryToPreserveScriptSignature = pMedium->GetFilter() && pFilter && pMedium->GetFilter()->GetFilterName() == pFilter->GetFilterName(); 1215 1216 bNoPreserveForOasis = ( 1217 (aODFVersion.equals( ODFVER_012_TEXT ) && nVersion == SvtSaveOptions::ODFVER_011) || 1218 (!aODFVersion.getLength() && nVersion >= SvtSaveOptions::ODFVER_012) 1219 ); 1220 } 1221 } 1222 1223 sal_Bool bCopyTo = sal_False; 1224 SfxItemSet *pMedSet = rMedium.GetItemSet(); 1225 if( pMedSet ) 1226 { 1227 SFX_ITEMSET_ARG( pMedSet, pSaveToItem, SfxBoolItem, SID_SAVETO, sal_False ); 1228 bCopyTo = GetCreateMode() == SFX_CREATE_MODE_EMBEDDED || 1229 (pSaveToItem && pSaveToItem->GetValue()); 1230 } 1231 1232 // use UCB for case sensitive/insensitive file name comparison 1233 if ( pMedium 1234 && pMedium->GetName().CompareIgnoreCaseToAscii( "private:stream", 14 ) != COMPARE_EQUAL 1235 && rMedium.GetName().CompareIgnoreCaseToAscii( "private:stream", 14 ) != COMPARE_EQUAL 1236 && ::utl::UCBContentHelper::EqualURLs( pMedium->GetName(), rMedium.GetName() ) ) 1237 { 1238 bStoreToSameLocation = sal_True; 1239 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save" ) ) ); 1240 1241 if ( pMedium->DocNeedsFileDateCheck() ) 1242 rMedium.CheckFileDate( pMedium->GetInitFileDate( sal_False ) ); 1243 1244 if ( bCopyTo && GetCreateMode() != SFX_CREATE_MODE_EMBEDDED ) 1245 { 1246 // export to the same location is vorbidden 1247 SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 1248 } 1249 else 1250 { 1251 // before we overwrite the original file, we will make a backup if there is a demand for that 1252 // if the backup is not created here it will be created internally and will be removed in case of successful saving 1253 const sal_Bool bDoBackup = SvtSaveOptions().IsBackup(); 1254 if ( bDoBackup ) 1255 { 1256 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "DoBackup" ) ) ); 1257 rMedium.DoBackup_Impl(); 1258 if ( rMedium.GetError() ) 1259 { 1260 SetError( rMedium.GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 1261 rMedium.ResetError(); 1262 } 1263 } 1264 1265 if ( bStorageBasedSource && bStorageBasedTarget ) 1266 { 1267 // The active storage must be switched. The simple saving is not enough. 1268 // The problem is that the target medium contains target MediaDescriptor. 1269 1270 // In future the switch of the persistance could be done on stream level: 1271 // a new wrapper service will be implemented that allows to exchange 1272 // persistance on the fly. So the real persistance will be set 1273 // to that stream only after successful commit of the storage. 1274 // TODO/LATER: 1275 // create wrapper stream based on the URL 1276 // create a new storage based on this stream 1277 // store to this new storage 1278 // commit the new storage 1279 // call saveCompleted based with this new storage ( get rid of old storage and "frees" URL ) 1280 // commit the wrapper stream ( the stream will connect the URL only on commit, after that it will hold it ) 1281 // if the last step is failed the stream should stay to be transacted and should be commited on any flush 1282 // so we can forget the stream in any way and the next storage commit will flush it 1283 1284 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Own to Own" ) ) ); 1285 1286 bNeedsDisconnectionOnFail = DisconnectStorage_Impl( 1287 *pMedium, rMedium ); 1288 if ( bNeedsDisconnectionOnFail 1289 || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) ) 1290 { 1291 pMedium->CloseAndRelease(); 1292 1293 // TODO/LATER: for now the medium must be closed since it can already contain streams from old medium 1294 // in future those streams should not be copied in case a valid target url is provided, 1295 // if the url is not provided ( means the document is based on a stream ) this code is not 1296 // reachable. 1297 rMedium.CloseAndRelease(); 1298 rMedium.GetOutputStorage(); 1299 } 1300 } 1301 else if ( !bStorageBasedSource && !bStorageBasedTarget ) 1302 { 1303 // the source and the target formats are alien 1304 // just disconnect the stream from the source format 1305 // so that the target medium can use it 1306 1307 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Alien to Alien" ) ) ); 1308 1309 pMedium->CloseAndRelease(); 1310 rMedium.CloseAndRelease(); 1311 rMedium.CreateTempFileNoCopy(); 1312 rMedium.GetOutStream(); 1313 } 1314 else if ( !bStorageBasedSource && bStorageBasedTarget ) 1315 { 1316 // the source format is an alien one but the target 1317 // format is an own one so just disconnect the source 1318 // medium 1319 1320 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Alien to Own" ) ) ); 1321 1322 pMedium->CloseAndRelease(); 1323 rMedium.CloseAndRelease(); 1324 rMedium.GetOutputStorage(); 1325 } 1326 else // means if ( bStorageBasedSource && !bStorageBasedTarget ) 1327 { 1328 // the source format is an own one but the target is 1329 // an alien format, just connect the source to temporary 1330 // storage 1331 1332 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Own to Alien" ) ) ); 1333 1334 bNeedsDisconnectionOnFail = DisconnectStorage_Impl( 1335 *pMedium, rMedium ); 1336 if ( bNeedsDisconnectionOnFail 1337 || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) ) 1338 { 1339 pMedium->CloseAndRelease(); 1340 rMedium.CloseAndRelease(); 1341 rMedium.CreateTempFileNoCopy(); 1342 rMedium.GetOutStream(); 1343 } 1344 } 1345 } 1346 } 1347 else 1348 { 1349 // This is SaveAs or export action, prepare the target medium 1350 // the alien filters still might write directly to the file, that is of course a bug, 1351 // but for now the framework has to be ready for it 1352 // TODO/LATER: let the medium be prepared for alien formats as well 1353 1354 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "SaveAs/Export" ) ) ); 1355 1356 rMedium.CloseAndRelease(); 1357 if ( bStorageBasedTarget ) 1358 { 1359 rMedium.GetOutputStorage(); 1360 } 1361 } 1362 1363 // TODO/LATER: error handling 1364 if( rMedium.GetErrorCode() || pMedium->GetErrorCode() || GetErrorCode() ) 1365 return sal_False; 1366 1367 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Locking" ) ) ); 1368 1369 rMedium.LockOrigFileOnDemand( sal_False, sal_False ); 1370 1371 if ( bStorageBasedTarget ) 1372 { 1373 if ( rMedium.GetErrorCode() ) 1374 return sal_False; 1375 1376 // If the filter is a "cross export" filter ( f.e. a filter for exporting an impress document from 1377 // a draw document ), the ClassId of the destination storage is different from the ClassId of this 1378 // document. It can be retrieved from the default filter for the desired target format 1379 long nFormat = rMedium.GetFilter()->GetFormat(); 1380 SfxFilterMatcher& rMatcher = SFX_APP()->GetFilterMatcher(); 1381 const SfxFilter *pFilt = rMatcher.GetFilter4ClipBoardId( nFormat ); 1382 if ( pFilt ) 1383 { 1384 if ( pFilt->GetServiceName() != rMedium.GetFilter()->GetServiceName() ) 1385 { 1386 datatransfer::DataFlavor aDataFlavor; 1387 SotExchange::GetFormatDataFlavor( nFormat, aDataFlavor ); 1388 1389 try 1390 { 1391 uno::Reference< beans::XPropertySet > xProps( rMedium.GetStorage(), uno::UNO_QUERY ); 1392 DBG_ASSERT( xProps.is(), "The storage implementation must implement XPropertySet!" ); 1393 if ( !xProps.is() ) 1394 throw uno::RuntimeException(); 1395 1396 xProps->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ), 1397 uno::makeAny( aDataFlavor.MimeType ) ); 1398 } 1399 catch( uno::Exception& ) 1400 { 1401 } 1402 } 1403 } 1404 } 1405 1406 // TODO/LATER: error handling 1407 if( rMedium.GetErrorCode() || pMedium->GetErrorCode() || GetErrorCode() ) 1408 return sal_False; 1409 1410 sal_Bool bOldStat = pImp->bForbidReload; 1411 pImp->bForbidReload = sal_True; 1412 1413 // lock user interface while saving the document 1414 Lock_Impl( this, sal_True ); 1415 1416 sal_Bool bOk = sal_False; 1417 // TODO/LATER: get rid of bOk 1418 1419 if( bOwnTarget && !( pFilter->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) ) 1420 { 1421 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing in own format." ) ) ); 1422 uno::Reference< embed::XStorage > xMedStorage = rMedium.GetStorage(); 1423 if ( !xMedStorage.is() ) 1424 { 1425 // no saving without storage, unlock UI and return 1426 Lock_Impl( this, sal_False ); 1427 pImp->bForbidReload = bOldStat; 1428 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing failed, still no error set." ) ) ); 1429 return sal_False; 1430 } 1431 1432 // transfer password from the parameters to the storage 1433 uno::Sequence< beans::NamedValue > aEncryptionData; 1434 sal_Bool bPasswdProvided = sal_False; 1435 if ( GetEncryptionData_Impl( rMedium.GetItemSet(), aEncryptionData ) ) 1436 { 1437 bPasswdProvided = sal_True; 1438 try { 1439 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage, aEncryptionData ); 1440 bOk = sal_True; 1441 } 1442 catch( uno::Exception& ) 1443 { 1444 DBG_ERROR( "Setting of common encryption key failed!" ); 1445 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 1446 } 1447 } 1448 else 1449 bOk = sal_True; 1450 1451 pFilter = rMedium.GetFilter(); 1452 1453 const SfxStringItem *pVersionItem = pSet ? (const SfxStringItem*) 1454 SfxRequest::GetItem( pSet, SID_DOCINFO_COMMENTS, sal_False, TYPE(SfxStringItem) ) : NULL; 1455 ::rtl::OUString aTmpVersionURL; 1456 1457 if ( bOk ) 1458 { 1459 bOk = sal_False; 1460 // currently the case that the storage is the same should be impossible 1461 if ( xMedStorage == GetStorage() ) 1462 { 1463 OSL_ENSURE( !pVersionItem, "This scenario is impossible currently!\n" ); 1464 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Should be impossible." ) ) ); 1465 // usual save procedure 1466 bOk = Save(); 1467 } 1468 else 1469 { 1470 // save to target 1471 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save as own format." ) ) ); 1472 bOk = SaveAsOwnFormat( rMedium ); 1473 if ( bOk && pVersionItem ) 1474 { 1475 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "pVersionItem != NULL" ) ) ); 1476 aTmpVersionURL = CreateTempCopyOfStorage_Impl( xMedStorage ); 1477 bOk = ( aTmpVersionURL.getLength() > 0 ); 1478 } 1479 } 1480 } 1481 1482 1483 if ( bOk && GetCreateMode() != SFX_CREATE_MODE_EMBEDDED && !bPasswdProvided ) 1484 { 1485 // store the thumbnail representation image 1486 // the thumbnail is not stored in case of encrypted document 1487 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Thumbnail creation." ) ) ); 1488 if ( !GenerateAndStoreThumbnail( bPasswdProvided, 1489 sal_False, 1490 pFilter->IsOwnTemplateFormat(), 1491 xMedStorage ) ) 1492 { 1493 // TODO: error handling 1494 OSL_ENSURE( sal_False, "Couldn't store thumbnail representation!" ); 1495 } 1496 } 1497 1498 if ( bOk ) 1499 { 1500 if ( pImp->bIsSaving || pImp->bPreserveVersions ) 1501 { 1502 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Preserve versions." ) ) ); 1503 try 1504 { 1505 Sequence < util::RevisionTag > aVersions = rMedium.GetVersionList(); 1506 if ( aVersions.getLength() ) 1507 { 1508 // copy the version streams 1509 ::rtl::OUString aVersionsName( RTL_CONSTASCII_USTRINGPARAM( "Versions" ) ); 1510 uno::Reference< embed::XStorage > xNewVerStor = xMedStorage->openStorageElement( 1511 aVersionsName, 1512 embed::ElementModes::READWRITE ); 1513 uno::Reference< embed::XStorage > xOldVerStor = GetStorage()->openStorageElement( 1514 aVersionsName, 1515 embed::ElementModes::READ ); 1516 if ( !xNewVerStor.is() || !xOldVerStor.is() ) 1517 throw uno::RuntimeException(); 1518 1519 for ( sal_Int32 n=0; n<aVersions.getLength(); n++ ) 1520 { 1521 if ( xOldVerStor->hasByName( aVersions[n].Identifier ) ) 1522 xOldVerStor->copyElementTo( aVersions[n].Identifier, xNewVerStor, aVersions[n].Identifier ); 1523 } 1524 1525 uno::Reference< embed::XTransactedObject > xTransact( xNewVerStor, uno::UNO_QUERY ); 1526 if ( xTransact.is() ) 1527 xTransact->commit(); 1528 } 1529 } 1530 catch( uno::Exception& ) 1531 { 1532 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Preserve versions has failed." ) ) ); 1533 DBG_ERROR( "Couldn't copy versions!\n" ); 1534 bOk = sal_False; 1535 // TODO/LATER: a specific error could be set 1536 } 1537 } 1538 1539 if ( bOk && pVersionItem ) 1540 { 1541 // store a version also 1542 const SfxStringItem *pAuthorItem = pSet ? (const SfxStringItem*) 1543 SfxRequest::GetItem( pSet, SID_DOCINFO_AUTHOR, sal_False, TYPE(SfxStringItem) ) : NULL; 1544 1545 // version comment 1546 util::RevisionTag aInfo; 1547 aInfo.Comment = pVersionItem->GetValue(); 1548 1549 // version author 1550 String aAuthor; 1551 if ( pAuthorItem ) 1552 aInfo.Author = pAuthorItem->GetValue(); 1553 else 1554 // if not transferred as a parameter, get it from user settings 1555 aInfo.Author = SvtUserOptions().GetFullName(); 1556 1557 DateTime aTime; 1558 aInfo.TimeStamp.Day = aTime.GetDay(); 1559 aInfo.TimeStamp.Month = aTime.GetMonth(); 1560 aInfo.TimeStamp.Year = aTime.GetYear(); 1561 aInfo.TimeStamp.Hours = aTime.GetHour(); 1562 aInfo.TimeStamp.Minutes = aTime.GetMin(); 1563 aInfo.TimeStamp.Seconds = aTime.GetSec(); 1564 1565 if ( bOk ) 1566 { 1567 // add new version information into the versionlist and save the versionlist 1568 // the version list must have been transferred from the "old" medium before 1569 rMedium.AddVersion_Impl( aInfo ); 1570 rMedium.SaveVersionList_Impl( sal_True ); 1571 bOk = PutURLContentsToVersionStream_Impl( aTmpVersionURL, xMedStorage, aInfo.Identifier ); 1572 } 1573 } 1574 else if ( bOk && ( pImp->bIsSaving || pImp->bPreserveVersions ) ) 1575 { 1576 rMedium.SaveVersionList_Impl( sal_True ); 1577 } 1578 } 1579 1580 if ( aTmpVersionURL.getLength() ) 1581 ::utl::UCBContentHelper::Kill( aTmpVersionURL ); 1582 } 1583 else 1584 { 1585 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing in alien format." ) ) ); 1586 // it's a "SaveAs" in an alien format 1587 if ( rMedium.GetFilter() && ( rMedium.GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) ) 1588 bOk = ExportTo( rMedium ); 1589 else 1590 bOk = ConvertTo( rMedium ); 1591 1592 // after saving the document, the temporary object storage must be updated 1593 // if the old object storage was not a temporary one, it will be updated also, because it will be used 1594 // as a source for copying the objects into the new temporary storage that will be created below 1595 // updating means: all child objects must be stored into it 1596 // ( same as on loading, where these objects are copied to the temporary storage ) 1597 // but don't commit these changes, because in the case when the old object storage is not a temporary one, 1598 // all changes will be written into the original file ! 1599 1600 if( bOk && !bCopyTo ) 1601 // we also don't touch any graphical replacements here 1602 bOk = SaveChildren( sal_True ); 1603 } 1604 1605 if ( bOk ) 1606 { 1607 // if ODF version of oasis format changes on saving the signature should not be preserved 1608 if ( bOk && bTryToPreserveScriptSignature && bNoPreserveForOasis ) 1609 bTryToPreserveScriptSignature = ( SotStorage::GetVersion( rMedium.GetStorage() ) == SOFFICE_FILEFORMAT_60 ); 1610 1611 uno::Reference< security::XDocumentDigitalSignatures > xDDSigns; 1612 if ( bOk && bTryToPreserveScriptSignature ) 1613 { 1614 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Copying scripting signature." ) ) ); 1615 1616 // if the scripting code was not changed and it is signed the signature should be preserved 1617 // unfortunately at this point we have only information whether the basic code has changed or not 1618 // so the only way is to check the signature if the basic was not changed 1619 try 1620 { 1621 // get the ODF version of the new medium 1622 uno::Sequence< uno::Any > aArgs( 1 ); 1623 aArgs[0] <<= ::rtl::OUString(); 1624 try 1625 { 1626 uno::Reference < beans::XPropertySet > xPropSet( rMedium.GetStorage(), uno::UNO_QUERY_THROW ); 1627 aArgs[0] = xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ); 1628 } 1629 catch( uno::Exception& ) 1630 { 1631 } 1632 1633 xDDSigns = uno::Reference< security::XDocumentDigitalSignatures >( 1634 comphelper::getProcessServiceFactory()->createInstanceWithArguments( 1635 rtl::OUString( 1636 RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ), 1637 aArgs ), 1638 uno::UNO_QUERY_THROW ); 1639 1640 ::rtl::OUString aScriptSignName = xDDSigns->getScriptingContentSignatureDefaultStreamName(); 1641 1642 if ( aScriptSignName.getLength() ) 1643 { 1644 pMedium->Close(); 1645 1646 // target medium is still not commited, it should not be closed 1647 // commit the package storage and close it, but leave the streams open 1648 rMedium.StorageCommit_Impl(); 1649 rMedium.CloseStorage(); 1650 1651 uno::Reference< embed::XStorage > xReadOrig = pMedium->GetZipStorageToSign_Impl(); 1652 if ( !xReadOrig.is() ) 1653 throw uno::RuntimeException(); 1654 uno::Reference< embed::XStorage > xMetaInf = xReadOrig->openStorageElement( 1655 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ), 1656 embed::ElementModes::READ ); 1657 1658 uno::Reference< embed::XStorage > xTarget = rMedium.GetZipStorageToSign_Impl( sal_False ); 1659 if ( !xTarget.is() ) 1660 throw uno::RuntimeException(); 1661 uno::Reference< embed::XStorage > xTargetMetaInf = xTarget->openStorageElement( 1662 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ), 1663 embed::ElementModes::READWRITE ); 1664 1665 if ( xMetaInf.is() && xTargetMetaInf.is() ) 1666 { 1667 xMetaInf->copyElementTo( aScriptSignName, xTargetMetaInf, aScriptSignName ); 1668 1669 uno::Reference< embed::XTransactedObject > xTransact( xTargetMetaInf, uno::UNO_QUERY ); 1670 if ( xTransact.is() ) 1671 xTransact->commit(); 1672 1673 xTargetMetaInf->dispose(); 1674 1675 // now check the copied signature 1676 uno::Sequence< security::DocumentSignatureInformation > aInfos = 1677 xDDSigns->verifyScriptingContentSignatures( xTarget, 1678 uno::Reference< io::XInputStream >() ); 1679 sal_uInt16 nState = ImplCheckSignaturesInformation( aInfos ); 1680 if ( nState == SIGNATURESTATE_SIGNATURES_OK || nState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED 1681 || nState == SIGNATURESTATE_SIGNATURES_PARTIAL_OK) 1682 { 1683 rMedium.SetCachedSignatureState_Impl( nState ); 1684 1685 // commit the ZipStorage from target medium 1686 xTransact.set( xTarget, uno::UNO_QUERY ); 1687 if ( xTransact.is() ) 1688 xTransact->commit(); 1689 } 1690 else 1691 { 1692 // it should not happen, the copies signature is invalid! 1693 // throw the changes away 1694 OSL_ASSERT( "An invalid signature was copied!" ); 1695 } 1696 } 1697 } 1698 } 1699 catch( uno::Exception& ) 1700 { 1701 } 1702 1703 pMedium->Close(); 1704 rMedium.CloseZipStorage_Impl(); 1705 } 1706 1707 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Medium commit." ) ) ); 1708 1709 // transfer data to its destinated location 1710 // the medium commits the storage or the stream it is based on 1711 RegisterTransfer( rMedium ); 1712 bOk = rMedium.Commit(); 1713 1714 if ( bOk ) 1715 { 1716 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing is successful." ) ) ); 1717 1718 // if the target medium is an alien format and the "old" medium was an own format and the "old" medium 1719 // has a name, the object storage must be exchanged, because now we need a new temporary storage 1720 // as object storage 1721 if ( !bCopyTo && bStorageBasedSource && !bStorageBasedTarget ) 1722 { 1723 if ( bStoreToSameLocation ) 1724 { 1725 // if the old medium already disconnected from document storage, the storage still must 1726 // be switched if backup file is used 1727 if ( bNeedsDisconnectionOnFail ) 1728 ConnectTmpStorage_Impl( pImp->m_xDocStorage, NULL ); 1729 } 1730 else if ( pMedium->GetName().Len() 1731 || ( pMedium->HasStorage_Impl() && pMedium->WillDisposeStorageOnClose_Impl() ) ) 1732 { 1733 OSL_ENSURE( pMedium->GetName().Len(), "Fallback is used, the medium without name should not dispose the storage!\n" ); 1734 // copy storage of old medium to new temporary storage and take this over 1735 if( !ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) ) 1736 { 1737 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Process after storing has failed." ) ) ); 1738 bOk = sal_False; 1739 } 1740 } 1741 } 1742 } 1743 else 1744 { 1745 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing has failed." ) ) ); 1746 1747 // in case the document storage was connected to backup temporarely it must be disconnected now 1748 if ( bNeedsDisconnectionOnFail ) 1749 ConnectTmpStorage_Impl( pImp->m_xDocStorage, NULL ); 1750 } 1751 } 1752 1753 // unlock user interface 1754 Lock_Impl( this, sal_False ); 1755 pImp->bForbidReload = bOldStat; 1756 1757 if ( bOk ) 1758 { 1759 try 1760 { 1761 ::ucbhelper::Content aContent( rMedium.GetName(), com::sun::star::uno::Reference < XCommandEnvironment >() ); 1762 com::sun::star::uno::Reference < XPropertySetInfo > xProps = aContent.getProperties(); 1763 if ( xProps.is() ) 1764 { 1765 ::rtl::OUString aAuthor( RTL_CONSTASCII_USTRINGPARAM("Author") ); 1766 ::rtl::OUString aKeywords( RTL_CONSTASCII_USTRINGPARAM("Keywords") ); 1767 ::rtl::OUString aSubject( RTL_CONSTASCII_USTRINGPARAM("Subject") ); 1768 Any aAny; 1769 1770 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( 1771 GetModel(), uno::UNO_QUERY_THROW); 1772 uno::Reference<document::XDocumentProperties> xDocProps 1773 = xDPS->getDocumentProperties(); 1774 1775 if ( xProps->hasPropertyByName( aAuthor ) ) 1776 { 1777 aAny <<= xDocProps->getAuthor(); 1778 aContent.setPropertyValue( aAuthor, aAny ); 1779 } 1780 if ( xProps->hasPropertyByName( aKeywords ) ) 1781 { 1782 aAny <<= ::comphelper::string::convertCommaSeparated( 1783 xDocProps->getKeywords()); 1784 aContent.setPropertyValue( aKeywords, aAny ); 1785 } 1786 if ( xProps->hasPropertyByName( aSubject ) ) 1787 { 1788 aAny <<= xDocProps->getSubject(); 1789 aContent.setPropertyValue( aSubject, aAny ); 1790 } 1791 } 1792 } 1793 catch( Exception& ) 1794 { 1795 } 1796 1797 #ifdef OS2 1798 { 1799 #define CHAR_POINTER(THE_OUSTRING) ::rtl::OUStringToOString (THE_OUSTRING, RTL_TEXTENCODING_UTF8).pData->buffer 1800 // Header for a single-valued ASCII EA data item 1801 typedef struct _EA_ASCII_header { 1802 sal_uInt16 usAttr; /* value: EAT_ASCII */ 1803 sal_uInt16 usLen; /* length of data */ 1804 CHAR szType[_MAX_PATH]; /* ASCII data fits in here ... */ 1805 } EA_ASCII_HEADER; 1806 char filePath[_MAX_PATH]; 1807 char fileExt[_MAX_PATH]; 1808 char docType[_MAX_PATH]; 1809 int rc; 1810 oslFileError eRet; 1811 ::rtl::OUString aSystemFileURL; 1812 const ::rtl::OUString aFileURL = rMedium.GetName(); 1813 // close medium 1814 rMedium.Close(); 1815 1816 // convert file URL to system path 1817 if (osl::FileBase::getSystemPathFromFileURL( aFileURL, aSystemFileURL) == osl::FileBase::E_None) { 1818 EA_ASCII_HEADER eaAscii; 1819 struct _ea eaType; 1820 strcpy( filePath, CHAR_POINTER( aSystemFileURL)); 1821 strcpy( docType, CHAR_POINTER( rMedium.GetFilter()->GetServiceName())); 1822 #if OSL_DEBUG_LEVEL>1 1823 printf( "file name: %s\n", filePath); 1824 printf( "filter name: %s\n", CHAR_POINTER(rMedium.GetFilter()->GetFilterName())); 1825 printf( "service name: %s\n", docType); 1826 #endif 1827 // initialize OS/2 EA data structure 1828 eaAscii.usAttr = EAT_ASCII; 1829 _splitpath ( filePath, NULL, NULL, NULL, fileExt); 1830 if (!stricmp( fileExt, ".pdf")) 1831 strcpy( eaAscii.szType, "Acrobat Document"); 1832 else if (!strcmp( docType, "com.sun.star.text.TextDocument")) 1833 strcpy( eaAscii.szType, "OpenOfficeOrg Writer Document"); 1834 else if (!strcmp( docType, "com.sun.star.sheet.SpreadsheetDocument")) 1835 strcpy( eaAscii.szType, "OpenOfficeOrg Calc Document"); 1836 else if (!strcmp( docType, "com.sun.star.presentation.PresentationDocument")) 1837 strcpy( eaAscii.szType, "OpenOfficeOrg Impress Document"); 1838 else if (!strcmp( docType, "com.sun.star.drawing.DrawingDocument")) 1839 strcpy( eaAscii.szType, "OpenOfficeOrg Draw Document"); 1840 else 1841 strcpy( eaAscii.szType, "OpenOfficeOrg Document"); 1842 eaAscii.usLen = strlen( eaAscii.szType); 1843 // fill libc EA data structure 1844 eaType.flags = 0; 1845 eaType.size = sizeof(sal_uInt16)*2 + eaAscii.usLen; 1846 eaType.value = &eaAscii; 1847 // put EA to file 1848 rc = _ea_put( &eaType, filePath, 0, ".TYPE"); 1849 #if OSL_DEBUG_LEVEL>1 1850 printf( "ea name: %s, rc %d, errno %d\n", eaAscii.szType, rc, errno); 1851 #endif 1852 } 1853 } 1854 #endif 1855 1856 } 1857 1858 return bOk; 1859 } 1860 1861 //------------------------------------------------------------------------ 1862 sal_Bool SfxObjectShell::DisconnectStorage_Impl( SfxMedium& rSrcMedium, SfxMedium& rTargetMedium ) 1863 { 1864 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::DisconnectStorage_Impl" ); 1865 1866 // this method disconnects the storage from source medium, and attaches it to the backup created by the target medium 1867 1868 uno::Reference< embed::XStorage > xStorage = rSrcMedium.GetStorage(); 1869 1870 sal_Bool bResult = sal_False; 1871 if ( xStorage == pImp->m_xDocStorage ) 1872 { 1873 try 1874 { 1875 uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY_THROW ); 1876 ::rtl::OUString aBackupURL = rTargetMedium.GetBackup_Impl(); 1877 if ( !aBackupURL.getLength() ) 1878 { 1879 // the backup could not be created, try to disconnect the storage and close the source SfxMedium 1880 // in this case the optimization is not possible, connect storage to a temporary file 1881 rTargetMedium.ResetError(); 1882 xOptStorage->writeAndAttachToStream( uno::Reference< io::XStream >() ); 1883 rSrcMedium.CanDisposeStorage_Impl( sal_False ); 1884 rSrcMedium.Close(); 1885 1886 // now try to create the backup 1887 rTargetMedium.GetBackup_Impl(); 1888 } 1889 else 1890 { 1891 // the following call will only compare stream sizes 1892 // TODO/LATER: this is a very risky part, since if the URL contents are different from the storage 1893 // contents, the storag will be broken 1894 xOptStorage->attachToURL( aBackupURL, sal_True ); 1895 1896 // the storage is successfuly attached to backup, thus it it owned by the document not by the medium 1897 rSrcMedium.CanDisposeStorage_Impl( sal_False ); 1898 bResult = sal_True; 1899 } 1900 } 1901 catch ( uno::Exception& ) 1902 {} 1903 } 1904 1905 OSL_ENSURE( bResult, "Storage disconnecting has failed - affects performance!" ); 1906 1907 return bResult; 1908 } 1909 1910 //------------------------------------------------------------------------ 1911 1912 sal_Bool SfxObjectShell::ConnectTmpStorage_Impl( 1913 const uno::Reference< embed::XStorage >& xStorage, 1914 SfxMedium* pMediumArg ) 1915 1916 /* [Beschreibung] 1917 1918 Arbeitet die Applikation auf einem temporaeren Storage, 1919 so darf der temporaere Storage nicht aus dem SaveCompleted 1920 genommen werden. Daher wird in diesem Fall schon hier an 1921 den neuen Storage connected. SaveCompleted tut dann nichts. 1922 1923 */ 1924 1925 { 1926 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::ConnectTmpStorage_Impl" ); 1927 1928 sal_Bool bResult = sal_False; 1929 1930 if ( xStorage.is() ) 1931 { 1932 try 1933 { 1934 // the empty argument means that the storage will create temporary stream itself 1935 uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY_THROW ); 1936 xOptStorage->writeAndAttachToStream( uno::Reference< io::XStream >() ); 1937 1938 // the storage is successfuly disconnected from the original sources, thus the medium must not dispose it 1939 if ( pMediumArg ) 1940 pMediumArg->CanDisposeStorage_Impl( sal_False ); 1941 1942 bResult = sal_True; 1943 } 1944 catch( uno::Exception& ) 1945 { 1946 } 1947 1948 // if switching of the storage does not work for any reason ( nonroot storage for example ) use the old method 1949 if ( !bResult ) try 1950 { 1951 uno::Reference< embed::XStorage > xTmpStorage = ::comphelper::OStorageHelper::GetTemporaryStorage(); 1952 1953 DBG_ASSERT( xTmpStorage.is(), "If a storage can not be created an exception must be thrown!\n" ); 1954 if ( !xTmpStorage.is() ) 1955 throw uno::RuntimeException(); 1956 1957 // TODO/LATER: may be it should be done in SwitchPersistence also 1958 // TODO/LATER: find faster way to copy storage; perhaps sharing with backup?! 1959 xStorage->copyToStorage( xTmpStorage ); 1960 //CopyStoragesOfUnknownMediaType( xStorage, xTmpStorage ); 1961 bResult = SaveCompleted( xTmpStorage ); 1962 1963 if ( bResult ) 1964 { 1965 pImp->pBasicManager->setStorage( xTmpStorage ); 1966 1967 // Get rid of this workaround after issue i113914 is fixed 1968 try 1969 { 1970 uno::Reference< script::XStorageBasedLibraryContainer > xBasicLibraries( pImp->xBasicLibraries, uno::UNO_QUERY_THROW ); 1971 xBasicLibraries->setRootStorage( xTmpStorage ); 1972 } 1973 catch( uno::Exception& ) 1974 {} 1975 try 1976 { 1977 uno::Reference< script::XStorageBasedLibraryContainer > xDialogLibraries( pImp->xDialogLibraries, uno::UNO_QUERY_THROW ); 1978 xDialogLibraries->setRootStorage( xTmpStorage ); 1979 } 1980 catch( uno::Exception& ) 1981 {} 1982 } 1983 } 1984 catch( uno::Exception& ) 1985 {} 1986 1987 if ( !bResult ) 1988 { 1989 // TODO/LATER: may need error code setting based on exception 1990 SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 1991 } 1992 } 1993 1994 return bResult; 1995 } 1996 1997 //------------------------------------------------------------------------- 1998 1999 sal_Bool SfxObjectShell::DoSaveObjectAs( SfxMedium& rMedium, sal_Bool bCommit ) 2000 { 2001 sal_Bool bOk = sal_False; 2002 { 2003 ModifyBlocker_Impl aBlock( this ); 2004 2005 uno::Reference < embed::XStorage > xNewStor = rMedium.GetStorage(); 2006 if ( !xNewStor.is() ) 2007 return sal_False; 2008 2009 uno::Reference < beans::XPropertySet > xPropSet( xNewStor, uno::UNO_QUERY ); 2010 if ( xPropSet.is() ) 2011 { 2012 Any a = xPropSet->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) ); 2013 ::rtl::OUString aMediaType; 2014 if ( !(a>>=aMediaType) || !aMediaType.getLength() ) 2015 { 2016 OSL_ENSURE( sal_False, "The mediatype must be set already!\n" ); 2017 SetupStorage( xNewStor, SOFFICE_FILEFORMAT_CURRENT, sal_False ); 2018 } 2019 2020 pImp->bIsSaving = sal_False; 2021 bOk = SaveAsOwnFormat( rMedium ); 2022 2023 if ( bCommit ) 2024 { 2025 try { 2026 uno::Reference< embed::XTransactedObject > xTransact( xNewStor, uno::UNO_QUERY_THROW ); 2027 xTransact->commit(); 2028 } 2029 catch( uno::Exception& ) 2030 { 2031 DBG_ERROR( "The strotage was not commited on DoSaveAs!\n" ); 2032 } 2033 } 2034 } 2035 } 2036 2037 return bOk; 2038 } 2039 2040 //------------------------------------------------------------------------- 2041 // TODO/LATER: may be the call must be removed completelly 2042 sal_Bool SfxObjectShell::DoSaveAs( SfxMedium& rMedium ) 2043 { 2044 // hier kommen nur Root-Storages rein, die via Temp-File gespeichert werden 2045 rMedium.CreateTempFileNoCopy(); 2046 SetError(rMedium.GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2047 if ( GetError() ) 2048 return sal_False; 2049 2050 // copy version list from "old" medium to target medium, so it can be used on saving 2051 if ( pImp->bPreserveVersions ) 2052 rMedium.TransferVersionList_Impl( *pMedium ); 2053 2054 sal_Bool bRet = SaveTo_Impl( rMedium, NULL ); 2055 if ( !bRet ) 2056 SetError(rMedium.GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2057 return bRet; 2058 } 2059 2060 //------------------------------------------------------------------------- 2061 2062 sal_Bool SfxObjectShell::DoSaveCompleted( SfxMedium* pNewMed ) 2063 { 2064 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::DoSaveCompleted" ); 2065 2066 sal_Bool bOk = sal_True; 2067 sal_Bool bMedChanged = pNewMed && pNewMed!=pMedium; 2068 /* sal_Bool bCreatedTempStor = pNewMed && pMedium && 2069 IsPackageStorageFormat_Impl(*pMedium) && 2070 !IsPackageStorageFormat_Impl(*pNewMed) && 2071 pMedium->GetName().Len(); 2072 */ 2073 DBG_ASSERT( !pNewMed || pNewMed->GetError() == ERRCODE_NONE, "DoSaveCompleted: Medium has error!" ); 2074 2075 // delete Medium (and Storage!) after all notifications 2076 SfxMedium* pOld = pMedium; 2077 if ( bMedChanged ) 2078 { 2079 pMedium = pNewMed; 2080 pMedium->CanDisposeStorage_Impl( sal_True ); 2081 } 2082 2083 const SfxFilter *pFilter = pMedium ? pMedium->GetFilter() : 0; 2084 if ( pNewMed ) 2085 { 2086 if( bMedChanged ) 2087 { 2088 if( pNewMed->GetName().Len() ) 2089 bHasName = sal_True; 2090 Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED) ); 2091 getDocProperties()->setGenerator( 2092 ::utl::DocInfoHelper::GetGeneratorString() ); 2093 } 2094 2095 uno::Reference< embed::XStorage > xStorage; 2096 if ( !pFilter || IsPackageStorageFormat_Impl( *pMedium ) ) 2097 { 2098 uno::Reference < embed::XStorage > xOld = GetStorage(); 2099 2100 // when the package based medium is broken and has no storage or if the storage 2101 // is the same as the document storage the current document storage should be preserved 2102 xStorage = pMedium->GetStorage(); 2103 bOk = SaveCompleted( xStorage ); 2104 if ( bOk && xStorage.is() && xOld != xStorage 2105 && (!pOld || !pOld->HasStorage_Impl() || xOld != pOld->GetStorage() ) ) 2106 { 2107 // old own storage was not controlled by old Medium -> dispose it 2108 try { 2109 xOld->dispose(); 2110 } catch( uno::Exception& ) 2111 { 2112 // the storage is disposed already 2113 // can happen during reload scenario when the medium has disposed it during the closing 2114 // will be fixed in one of the next milestones 2115 } 2116 } 2117 } 2118 else 2119 { 2120 if( pMedium->GetOpenMode() & STREAM_WRITE ) 2121 pMedium->GetInStream(); 2122 xStorage = GetStorage(); 2123 } 2124 2125 // TODO/LATER: may be this code will be replaced, but not sure 2126 // Set storage in document library containers 2127 pImp->pBasicManager->setStorage( xStorage ); 2128 2129 // Get rid of this workaround after issue i113914 is fixed 2130 try 2131 { 2132 uno::Reference< script::XStorageBasedLibraryContainer > xBasicLibraries( pImp->xBasicLibraries, uno::UNO_QUERY_THROW ); 2133 xBasicLibraries->setRootStorage( xStorage ); 2134 } 2135 catch( uno::Exception& ) 2136 {} 2137 try 2138 { 2139 uno::Reference< script::XStorageBasedLibraryContainer > xDialogLibraries( pImp->xDialogLibraries, uno::UNO_QUERY_THROW ); 2140 xDialogLibraries->setRootStorage( xStorage ); 2141 } 2142 catch( uno::Exception& ) 2143 {} 2144 } 2145 else 2146 { 2147 if( pMedium ) 2148 { 2149 if( pFilter && !IsPackageStorageFormat_Impl( *pMedium ) && (pMedium->GetOpenMode() & STREAM_WRITE )) 2150 { 2151 pMedium->ReOpen(); 2152 bOk = SaveCompletedChildren( sal_False ); 2153 } 2154 else 2155 bOk = SaveCompleted( NULL ); 2156 } 2157 // entweder Save oder ConvertTo 2158 else 2159 bOk = SaveCompleted( NULL ); 2160 } 2161 2162 if ( bOk && pNewMed ) 2163 { 2164 if( bMedChanged ) 2165 { 2166 delete pOld; 2167 2168 uno::Reference< frame::XModel > xModel = GetModel(); 2169 if ( xModel.is() ) 2170 { 2171 ::rtl::OUString aURL = pNewMed->GetOrigURL(); 2172 uno::Sequence< beans::PropertyValue > aMediaDescr; 2173 TransformItems( SID_OPENDOC, *pNewMed->GetItemSet(), aMediaDescr ); 2174 try 2175 { 2176 xModel->attachResource( aURL, aMediaDescr ); 2177 } 2178 catch( uno::Exception& ) 2179 {} 2180 } 2181 2182 // before the title regenerated the document must loose the signatures 2183 pImp->nDocumentSignatureState = SIGNATURESTATE_NOSIGNATURES; 2184 pImp->nScriptingSignatureState = pNewMed->GetCachedSignatureState_Impl(); 2185 OSL_ENSURE( pImp->nScriptingSignatureState != SIGNATURESTATE_SIGNATURES_BROKEN, "The signature must not be broken at this place" ); 2186 pImp->bSignatureErrorIsShown = sal_False; 2187 2188 // TODO/LATER: in future the medium must control own signature state, not the document 2189 pNewMed->SetCachedSignatureState_Impl( SIGNATURESTATE_NOSIGNATURES ); // set the default value back 2190 2191 // Titel neu setzen 2192 if ( pNewMed->GetName().Len() && SFX_CREATE_MODE_EMBEDDED != eCreateMode ) 2193 InvalidateName(); 2194 SetModified(sal_False); // nur bei gesetztem Medium zur"ucksetzen 2195 Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED) ); 2196 2197 // this is the end of the saving process, it is possible that the file was changed 2198 // between medium commit and this step ( attributes change and so on ) 2199 // so get the file date again 2200 if ( pNewMed->DocNeedsFileDateCheck() ) 2201 pNewMed->GetInitFileDate( sal_True ); 2202 } 2203 } 2204 2205 pMedium->ClearBackup_Impl(); 2206 pMedium->LockOrigFileOnDemand( sal_True, sal_False ); 2207 2208 return bOk; 2209 } 2210 2211 //------------------------------------------------------------------------- 2212 2213 sal_Bool SfxObjectShell::ConvertFrom 2214 ( 2215 SfxMedium& /*rMedium*/ /* <SfxMedium>, welches die Quell-Datei beschreibt 2216 (z.B. Dateiname, <SfxFilter>, Open-Modi etc.) */ 2217 ) 2218 2219 /* [Beschreibung] 2220 2221 Diese Methode wird zum Laden von Dokumenten "uber alle Filter gerufen, 2222 die nicht SFX_FILTER_OWN sind oder f"ur die kein Clipboard-Format 2223 registriert wurde (also kein Storage-Format benutzen). Mit anderen Worten: 2224 mit dieser Methode wird importiert. 2225 2226 Das hier zu "offende File sollte "uber 'rMedium' ge"offnet werden, 2227 um die richtigen Open-Modi zu gew"ahrleisten. Insbesondere wenn das 2228 Format beibehalten wird (nur m"oglich bei SFX_FILTER_SIMULATE oder 2229 SFX_FILTER_ONW) mu\s die Datei STREAM_SHARE_DENYWRITE ge"offnet werden. 2230 2231 2232 [R"uckgabewert] 2233 2234 sal_Bool sal_True 2235 Das Dokument konnte geladen werden. 2236 2237 sal_False 2238 Das Dokument konnte nicht geladen werden, ein 2239 Fehlercode ist mit <SvMedium::GetError()const> zu 2240 erhalten. 2241 2242 2243 [Beispiel] 2244 2245 sal_Bool DocSh::ConvertFrom( SfxMedium &rMedium ) 2246 { 2247 SvStreamRef xStream = rMedium.GetInStream(); 2248 if( xStream.is() ) 2249 { 2250 xStream->SetBufferSize(4096); 2251 *xStream >> ...; 2252 2253 // NICHT 'rMedium.CloseInStream()' rufen! File gelockt halten! 2254 return SVSTREAM_OK == rMedium.GetError(); 2255 } 2256 2257 return sal_False; 2258 } 2259 2260 2261 [Querverweise] 2262 2263 <SfxObjectShell::ConvertTo(SfxMedium&)> 2264 <SFX_FILTER_REGISTRATION> 2265 */ 2266 { 2267 return sal_False; 2268 } 2269 2270 sal_Bool SfxObjectShell::InsertFrom( SfxMedium& rMedium ) 2271 { 2272 ::rtl::OUString aTypeName( rMedium.GetFilter()->GetTypeName() ); 2273 ::rtl::OUString aFilterName( rMedium.GetFilter()->GetFilterName() ); 2274 2275 uno::Reference< lang::XMultiServiceFactory > xMan = ::comphelper::getProcessServiceFactory(); 2276 uno::Reference < lang::XMultiServiceFactory > xFilterFact ( 2277 xMan->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY ); 2278 2279 uno::Sequence < beans::PropertyValue > aProps; 2280 uno::Reference < container::XNameAccess > xFilters ( xFilterFact, uno::UNO_QUERY ); 2281 if ( xFilters->hasByName( aFilterName ) ) 2282 { 2283 xFilters->getByName( aFilterName ) >>= aProps; 2284 rMedium.GetItemSet()->Put( SfxStringItem( SID_FILTER_NAME, aFilterName ) ); 2285 } 2286 2287 ::rtl::OUString aFilterImplName; 2288 sal_Int32 nFilterProps = aProps.getLength(); 2289 for ( sal_Int32 nFilterProp = 0; nFilterProp<nFilterProps; nFilterProp++ ) 2290 { 2291 const beans::PropertyValue& rFilterProp = aProps[nFilterProp]; 2292 if ( rFilterProp.Name.compareToAscii("FilterService") == COMPARE_EQUAL ) 2293 { 2294 rFilterProp.Value >>= aFilterImplName; 2295 break; 2296 } 2297 } 2298 2299 uno::Reference< document::XFilter > xLoader; 2300 if ( aFilterImplName.getLength() ) 2301 { 2302 try{ 2303 xLoader = uno::Reference< document::XFilter > 2304 ( xFilterFact->createInstanceWithArguments( aFilterName, uno::Sequence < uno::Any >() ), uno::UNO_QUERY ); 2305 }catch(const uno::Exception&) 2306 { xLoader.clear(); } 2307 } 2308 if ( xLoader.is() ) 2309 { 2310 // #131744#: it happens that xLoader does not support xImporter! 2311 try{ 2312 uno::Reference< lang::XComponent > xComp( GetModel(), uno::UNO_QUERY_THROW ); 2313 uno::Reference< document::XImporter > xImporter( xLoader, uno::UNO_QUERY_THROW ); 2314 xImporter->setTargetDocument( xComp ); 2315 2316 uno::Sequence < beans::PropertyValue > lDescriptor; 2317 rMedium.GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, rMedium.GetName() ) ); 2318 TransformItems( SID_OPENDOC, *rMedium.GetItemSet(), lDescriptor ); 2319 2320 com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aArgs ( lDescriptor.getLength() ); 2321 com::sun::star::beans::PropertyValue * pNewValue = aArgs.getArray(); 2322 const com::sun::star::beans::PropertyValue * pOldValue = lDescriptor.getConstArray(); 2323 const OUString sInputStream ( RTL_CONSTASCII_USTRINGPARAM ( "InputStream" ) ); 2324 2325 sal_Bool bHasInputStream = sal_False; 2326 sal_Bool bHasBaseURL = sal_False; 2327 sal_Int32 i; 2328 sal_Int32 nEnd = lDescriptor.getLength(); 2329 2330 for ( i = 0; i < nEnd; i++ ) 2331 { 2332 pNewValue[i] = pOldValue[i]; 2333 if ( pOldValue [i].Name == sInputStream ) 2334 bHasInputStream = sal_True; 2335 else if ( pOldValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "DocumentBaseURL" ) ) ) 2336 bHasBaseURL = sal_True; 2337 } 2338 2339 if ( !bHasInputStream ) 2340 { 2341 aArgs.realloc ( ++nEnd ); 2342 aArgs[nEnd-1].Name = sInputStream; 2343 aArgs[nEnd-1].Value <<= com::sun::star::uno::Reference < com::sun::star::io::XInputStream > ( new utl::OSeekableInputStreamWrapper ( *rMedium.GetInStream() ) ); 2344 } 2345 2346 if ( !bHasBaseURL ) 2347 { 2348 aArgs.realloc ( ++nEnd ); 2349 aArgs[nEnd-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "DocumentBaseURL" ) ); 2350 aArgs[nEnd-1].Value <<= rMedium.GetBaseURL(); 2351 } 2352 2353 aArgs.realloc( ++nEnd ); 2354 aArgs[nEnd-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "InsertMode" ) ); 2355 aArgs[nEnd-1].Value <<= (sal_Bool) sal_True; 2356 2357 return xLoader->filter( aArgs ); 2358 }catch(const uno::Exception&) 2359 {} 2360 } 2361 2362 return sal_False; 2363 } 2364 2365 sal_Bool SfxObjectShell::ImportFrom( SfxMedium& rMedium ) 2366 { 2367 ::rtl::OUString aTypeName( rMedium.GetFilter()->GetTypeName() ); 2368 ::rtl::OUString aFilterName( rMedium.GetFilter()->GetFilterName() ); 2369 2370 uno::Reference< lang::XMultiServiceFactory > xMan = ::comphelper::getProcessServiceFactory(); 2371 uno::Reference < lang::XMultiServiceFactory > xFilterFact ( 2372 xMan->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY ); 2373 2374 uno::Sequence < beans::PropertyValue > aProps; 2375 uno::Reference < container::XNameAccess > xFilters ( xFilterFact, uno::UNO_QUERY ); 2376 if ( xFilters->hasByName( aFilterName ) ) 2377 { 2378 xFilters->getByName( aFilterName ) >>= aProps; 2379 rMedium.GetItemSet()->Put( SfxStringItem( SID_FILTER_NAME, aFilterName ) ); 2380 } 2381 2382 ::rtl::OUString aFilterImplName; 2383 sal_Int32 nFilterProps = aProps.getLength(); 2384 for ( sal_Int32 nFilterProp = 0; nFilterProp<nFilterProps; nFilterProp++ ) 2385 { 2386 const beans::PropertyValue& rFilterProp = aProps[nFilterProp]; 2387 if ( rFilterProp.Name.compareToAscii("FilterService") == COMPARE_EQUAL ) 2388 { 2389 rFilterProp.Value >>= aFilterImplName; 2390 break; 2391 } 2392 } 2393 2394 uno::Reference< document::XFilter > xLoader; 2395 if ( aFilterImplName.getLength() ) 2396 { 2397 try{ 2398 xLoader = uno::Reference< document::XFilter > 2399 ( xFilterFact->createInstanceWithArguments( aFilterName, uno::Sequence < uno::Any >() ), uno::UNO_QUERY ); 2400 }catch(const uno::Exception&) 2401 { xLoader.clear(); } 2402 } 2403 if ( xLoader.is() ) 2404 { 2405 // #131744#: it happens that xLoader does not support xImporter! 2406 try{ 2407 uno::Reference< lang::XComponent > xComp( GetModel(), uno::UNO_QUERY_THROW ); 2408 uno::Reference< document::XImporter > xImporter( xLoader, uno::UNO_QUERY_THROW ); 2409 xImporter->setTargetDocument( xComp ); 2410 2411 uno::Sequence < beans::PropertyValue > lDescriptor; 2412 rMedium.GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, rMedium.GetName() ) ); 2413 TransformItems( SID_OPENDOC, *rMedium.GetItemSet(), lDescriptor ); 2414 2415 com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aArgs ( lDescriptor.getLength() ); 2416 com::sun::star::beans::PropertyValue * pNewValue = aArgs.getArray(); 2417 const com::sun::star::beans::PropertyValue * pOldValue = lDescriptor.getConstArray(); 2418 const OUString sInputStream ( RTL_CONSTASCII_USTRINGPARAM ( "InputStream" ) ); 2419 2420 sal_Bool bHasInputStream = sal_False; 2421 sal_Bool bHasBaseURL = sal_False; 2422 sal_Int32 i; 2423 sal_Int32 nEnd = lDescriptor.getLength(); 2424 2425 for ( i = 0; i < nEnd; i++ ) 2426 { 2427 pNewValue[i] = pOldValue[i]; 2428 if ( pOldValue [i].Name == sInputStream ) 2429 bHasInputStream = sal_True; 2430 else if ( pOldValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "DocumentBaseURL" ) ) ) 2431 bHasBaseURL = sal_True; 2432 } 2433 2434 if ( !bHasInputStream ) 2435 { 2436 aArgs.realloc ( ++nEnd ); 2437 aArgs[nEnd-1].Name = sInputStream; 2438 aArgs[nEnd-1].Value <<= com::sun::star::uno::Reference < com::sun::star::io::XInputStream > ( new utl::OSeekableInputStreamWrapper ( *rMedium.GetInStream() ) ); 2439 } 2440 2441 if ( !bHasBaseURL ) 2442 { 2443 aArgs.realloc ( ++nEnd ); 2444 aArgs[nEnd-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "DocumentBaseURL" ) ); 2445 aArgs[nEnd-1].Value <<= rMedium.GetBaseURL(); 2446 } 2447 2448 return xLoader->filter( aArgs ); 2449 }catch(const uno::Exception&) 2450 {} 2451 } 2452 2453 return sal_False; 2454 } 2455 2456 sal_Bool SfxObjectShell::ExportTo( SfxMedium& rMedium ) 2457 { 2458 ::rtl::OUString aTypeName( rMedium.GetFilter()->GetTypeName() ); 2459 ::rtl::OUString aFilterName( rMedium.GetFilter()->GetFilterName() ); 2460 uno::Reference< document::XExporter > xExporter; 2461 2462 { 2463 uno::Reference< lang::XMultiServiceFactory > xMan = ::comphelper::getProcessServiceFactory(); 2464 uno::Reference < lang::XMultiServiceFactory > xFilterFact ( 2465 xMan->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY ); 2466 2467 uno::Sequence < beans::PropertyValue > aProps; 2468 uno::Reference < container::XNameAccess > xFilters ( xFilterFact, uno::UNO_QUERY ); 2469 if ( xFilters->hasByName( aFilterName ) ) 2470 xFilters->getByName( aFilterName ) >>= aProps; 2471 2472 ::rtl::OUString aFilterImplName; 2473 sal_Int32 nFilterProps = aProps.getLength(); 2474 for ( sal_Int32 nFilterProp = 0; nFilterProp<nFilterProps; nFilterProp++ ) 2475 { 2476 const beans::PropertyValue& rFilterProp = aProps[nFilterProp]; 2477 if ( rFilterProp.Name.compareToAscii("FilterService") == COMPARE_EQUAL ) 2478 { 2479 rFilterProp.Value >>= aFilterImplName; 2480 break; 2481 } 2482 } 2483 2484 if ( aFilterImplName.getLength() ) 2485 { 2486 try{ 2487 xExporter = uno::Reference< document::XExporter > 2488 ( xFilterFact->createInstanceWithArguments( aFilterName, uno::Sequence < uno::Any >() ), uno::UNO_QUERY ); 2489 }catch(const uno::Exception&) 2490 { xExporter.clear(); } 2491 } 2492 } 2493 2494 if ( xExporter.is() ) 2495 { 2496 try{ 2497 uno::Reference< lang::XComponent > xComp( GetModel(), uno::UNO_QUERY_THROW ); 2498 uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY_THROW ); 2499 xExporter->setSourceDocument( xComp ); 2500 2501 com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aOldArgs; 2502 SfxItemSet* pItems = rMedium.GetItemSet(); 2503 TransformItems( SID_SAVEASDOC, *pItems, aOldArgs ); 2504 2505 const com::sun::star::beans::PropertyValue * pOldValue = aOldArgs.getConstArray(); 2506 com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aArgs ( aOldArgs.getLength() ); 2507 com::sun::star::beans::PropertyValue * pNewValue = aArgs.getArray(); 2508 2509 // put in the REAL file name, and copy all PropertyValues 2510 const OUString sOutputStream ( RTL_CONSTASCII_USTRINGPARAM ( "OutputStream" ) ); 2511 const OUString sStream ( RTL_CONSTASCII_USTRINGPARAM ( "StreamForOutput" ) ); 2512 sal_Bool bHasOutputStream = sal_False; 2513 sal_Bool bHasStream = sal_False; 2514 sal_Bool bHasBaseURL = sal_False; 2515 sal_Int32 i; 2516 sal_Int32 nEnd = aOldArgs.getLength(); 2517 2518 for ( i = 0; i < nEnd; i++ ) 2519 { 2520 pNewValue[i] = pOldValue[i]; 2521 if ( pOldValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "FileName" ) ) ) 2522 pNewValue[i].Value <<= OUString ( rMedium.GetName() ); 2523 else if ( pOldValue[i].Name == sOutputStream ) 2524 bHasOutputStream = sal_True; 2525 else if ( pOldValue[i].Name == sStream ) 2526 bHasStream = sal_True; 2527 else if ( pOldValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "DocumentBaseURL" ) ) ) 2528 bHasBaseURL = sal_True; 2529 } 2530 2531 if ( !bHasOutputStream ) 2532 { 2533 aArgs.realloc ( ++nEnd ); 2534 aArgs[nEnd-1].Name = sOutputStream; 2535 aArgs[nEnd-1].Value <<= com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > ( new utl::OOutputStreamWrapper ( *rMedium.GetOutStream() ) ); 2536 } 2537 2538 // add stream as well, for OOX export and maybe others 2539 if ( !bHasStream ) 2540 { 2541 aArgs.realloc ( ++nEnd ); 2542 aArgs[nEnd-1].Name = sStream; 2543 aArgs[nEnd-1].Value <<= com::sun::star::uno::Reference < com::sun::star::io::XStream > ( new utl::OStreamWrapper ( *rMedium.GetOutStream() ) ); 2544 } 2545 2546 if ( !bHasBaseURL ) 2547 { 2548 aArgs.realloc ( ++nEnd ); 2549 aArgs[nEnd-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "DocumentBaseURL" ) ); 2550 aArgs[nEnd-1].Value <<= rMedium.GetBaseURL( sal_True ); 2551 } 2552 2553 return xFilter->filter( aArgs ); 2554 }catch(const uno::Exception&) 2555 {} 2556 } 2557 2558 return sal_False; 2559 } 2560 2561 //------------------------------------------------------------------------- 2562 2563 sal_Bool SfxObjectShell::ConvertTo 2564 ( 2565 SfxMedium& /*rMedium*/ /* <SfxMedium>, welches die Ziel-Datei beschreibt 2566 (z.B. Dateiname, <SfxFilter>, Open-Modi etc.) */ 2567 ) 2568 2569 /* [Beschreibung] 2570 2571 Diese Methode wird zum Speichern von Dokumenten "uber alle Filter gerufen, 2572 die nicht SFX_FILTER_OWN sind oder f"ur die kein Clipboard-Format 2573 registriert wurde (also kein Storage-Format benutzen). Mit anderen Worten: 2574 mit dieser Methode wird exportiert. 2575 2576 Das hier zu "offende File sollte "uber 'rMedium' ge"offnet werden, 2577 um die richtigen Open-Modi zu gew"ahrleisten. Insbesondere wenn das 2578 Format beibehalten wird (nur m"oglich bei SFX_FILTER_SIMULATE oder 2579 SFX_FILTER_ONW) mu\s die Datei auch nach dem Speichern im Modus 2580 STREAM_SHARE_DENYWRITE ge"offnet bleiben. 2581 2582 2583 [R"uckgabewert] 2584 2585 sal_Bool sal_True 2586 Das Dokument konnte gespeichert werden. 2587 2588 sal_False 2589 Das Dokument konnte nicht gespeichert werden, ein 2590 Fehlercode ist mit <SvMedium::GetError()const> zu 2591 erhalten. 2592 2593 2594 [Beispiel] 2595 2596 sal_Bool DocSh::ConvertTo( SfxMedium &rMedium ) 2597 { 2598 SvStreamRef xStream = rMedium.GetOutStream(); 2599 if ( xStream.is() ) 2600 { 2601 xStream->SetBufferSize(4096); 2602 *xStream << ...; 2603 2604 rMedium.CloseOutStream(); // "offnet automatisch wieder den InStream 2605 return SVSTREAM_OK == rMedium.GetError(); 2606 } 2607 return sal_False ; 2608 } 2609 2610 2611 [Querverweise] 2612 2613 <SfxObjectShell::ConvertFrom(SfxMedium&)> 2614 <SFX_FILTER_REGISTRATION> 2615 */ 2616 2617 { 2618 return sal_False; 2619 } 2620 2621 //------------------------------------------------------------------------- 2622 2623 sal_Bool SfxObjectShell::DoSave_Impl( const SfxItemSet* pArgs ) 2624 { 2625 SfxMedium* pRetrMedium = GetMedium(); 2626 const SfxFilter* pFilter = pRetrMedium->GetFilter(); 2627 2628 // copy the original itemset, but remove the "version" item, because pMediumTmp 2629 // is a new medium "from scratch", so no version should be stored into it 2630 SfxItemSet* pSet = new SfxAllItemSet(*pRetrMedium->GetItemSet()); 2631 pSet->ClearItem( SID_VERSION ); 2632 pSet->ClearItem( SID_DOC_BASEURL ); 2633 2634 // create a medium as a copy; this medium is only for writingm, because it uses the same name as the original one 2635 // writing is done through a copy, that will be transferred to the target ( of course after calling HandsOff ) 2636 SfxMedium* pMediumTmp = new SfxMedium( pRetrMedium->GetName(), pRetrMedium->GetOpenMode(), pRetrMedium->IsDirect(), pFilter, pSet ); 2637 pMediumTmp->SetLongName( pRetrMedium->GetLongName() ); 2638 // pMediumTmp->CreateTempFileNoCopy(); 2639 if ( pMediumTmp->GetErrorCode() != ERRCODE_NONE ) 2640 { 2641 SetError( pMediumTmp->GetError(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2642 delete pMediumTmp; 2643 return sal_False; 2644 } 2645 2646 // copy version list from "old" medium to target medium, so it can be used on saving 2647 pMediumTmp->TransferVersionList_Impl( *pRetrMedium ); 2648 /* 2649 if ( pFilter && ( pFilter->GetFilterFlags() & SFX_FILTER_PACKED ) ) 2650 SetError( GetMedium()->Unpack_Impl( pRetrMedium->GetPhysicalName() ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2651 */ 2652 2653 // an interaction handler here can aquire only in case of GUI Saving 2654 // and should be removed after the saving is done 2655 com::sun::star::uno::Reference< XInteractionHandler > xInteract; 2656 SFX_ITEMSET_ARG( pArgs, pxInteractionItem, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False ); 2657 if ( pxInteractionItem && ( pxInteractionItem->GetValue() >>= xInteract ) && xInteract.is() ) 2658 pMediumTmp->GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER, makeAny( xInteract ) ) ); 2659 2660 sal_Bool bSaved = sal_False; 2661 if( !GetError() && SaveTo_Impl( *pMediumTmp, pArgs ) ) 2662 { 2663 bSaved = sal_True; 2664 2665 if( pMediumTmp->GetItemSet() ) 2666 { 2667 pMediumTmp->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER ); 2668 pMediumTmp->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL ); 2669 } 2670 2671 SetError(pMediumTmp->GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2672 2673 sal_Bool bOpen( sal_False ); 2674 bOpen = DoSaveCompleted( pMediumTmp ); 2675 DBG_ASSERT(bOpen,"Fehlerbehandlung fuer DoSaveCompleted nicht implementiert"); 2676 } 2677 else 2678 { 2679 // transfer error code from medium to objectshell 2680 SetError( pMediumTmp->GetError(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2681 2682 // reconnect to object storage 2683 DoSaveCompleted( 0 ); 2684 2685 if( pRetrMedium->GetItemSet() ) 2686 { 2687 pRetrMedium->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER ); 2688 pRetrMedium->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL ); 2689 } 2690 2691 delete pMediumTmp; 2692 } 2693 2694 SetModified( !bSaved ); 2695 return bSaved; 2696 } 2697 2698 //------------------------------------------------------------------------- 2699 2700 sal_Bool SfxObjectShell::Save_Impl( const SfxItemSet* pSet ) 2701 { 2702 if ( IsReadOnly() ) 2703 { 2704 SetError( ERRCODE_SFX_DOCUMENTREADONLY, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2705 return sal_False; 2706 } 2707 2708 DBG_CHKTHIS(SfxObjectShell, 0); 2709 2710 pImp->bIsSaving = sal_True; 2711 sal_Bool bSaved = sal_False; 2712 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False); 2713 if ( pSalvageItem ) 2714 { 2715 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False); 2716 String aFilterName; 2717 const SfxFilter *pFilter = NULL; 2718 if ( pFilterItem ) 2719 pFilter = SfxFilterMatcher( String::CreateFromAscii( GetFactory().GetShortName()) ).GetFilter4FilterName( aFilterName ); 2720 2721 SfxMedium *pMed = new SfxMedium( 2722 pSalvageItem->GetValue(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC, sal_False, pFilter ); 2723 2724 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False ); 2725 if ( pPasswordItem ) 2726 pMed->GetItemSet()->Put( *pPasswordItem ); 2727 2728 bSaved = DoSaveAs( *pMed ); 2729 if ( bSaved ) 2730 bSaved = DoSaveCompleted( pMed ); 2731 else 2732 delete pMed; 2733 } 2734 else 2735 bSaved = DoSave_Impl( pSet ); 2736 return bSaved; 2737 } 2738 2739 //------------------------------------------------------------------------- 2740 2741 sal_Bool SfxObjectShell::CommonSaveAs_Impl 2742 ( 2743 const INetURLObject& aURL, 2744 const String& aFilterName, 2745 SfxItemSet* aParams 2746 ) 2747 { 2748 if( aURL.HasError() ) 2749 { 2750 SetError( ERRCODE_IO_INVALIDPARAMETER, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2751 return sal_False; 2752 } 2753 2754 if ( aURL != INetURLObject( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:stream" ) ) ) ) 2755 { 2756 // gibt es schon ein Doc mit dem Namen? 2757 SfxObjectShell* pDoc = 0; 2758 for ( SfxObjectShell* pTmp = SfxObjectShell::GetFirst(); 2759 pTmp && !pDoc; 2760 pTmp = SfxObjectShell::GetNext(*pTmp) ) 2761 { 2762 if( ( pTmp != this ) && pTmp->GetMedium() ) 2763 { 2764 INetURLObject aCompare( pTmp->GetMedium()->GetName() ); 2765 if ( aCompare == aURL ) 2766 pDoc = pTmp; 2767 } 2768 } 2769 if ( pDoc ) 2770 { 2771 // dann Fehlermeldeung: "schon offen" 2772 SetError(ERRCODE_SFX_ALREADYOPEN, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); 2773 return sal_False; 2774 } 2775 } 2776 2777 DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "Illegal URL!" ); 2778 DBG_ASSERT( aParams->Count() != 0, "fehlerhafte Parameter"); 2779 2780 SFX_ITEMSET_ARG( aParams, pSaveToItem, SfxBoolItem, SID_SAVETO, sal_False ); 2781 sal_Bool bSaveTo = pSaveToItem ? pSaveToItem->GetValue() : sal_False; 2782 2783 const SfxFilter* pFilter = GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName ); 2784 if ( !pFilter 2785 || !pFilter->CanExport() 2786 || (!bSaveTo && !pFilter->CanImport()) ) 2787 { 2788 SetError( ERRCODE_IO_INVALIDPARAMETER, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2789 return sal_False; 2790 } 2791 2792 SFX_ITEMSET_ARG( aParams, pCopyStreamItem, SfxBoolItem, SID_COPY_STREAM_IF_POSSIBLE, sal_False ); 2793 if ( bSaveTo && pCopyStreamItem && pCopyStreamItem->GetValue() && !IsModified() ) 2794 { 2795 if ( pMedium->TryDirectTransfer( aURL.GetMainURL( INetURLObject::NO_DECODE ), *aParams ) ) 2796 return sal_True; 2797 } 2798 aParams->ClearItem( SID_COPY_STREAM_IF_POSSIBLE ); 2799 2800 pImp->bPasswd = aParams && SFX_ITEM_SET == aParams->GetItemState(SID_PASSWORD); 2801 2802 SfxMedium *pActMed = GetMedium(); 2803 const INetURLObject aActName(pActMed->GetName()); 2804 2805 sal_Bool bWasReadonly = IsReadOnly(); 2806 2807 if ( aURL == aActName && aURL != INetURLObject( OUString::createFromAscii( "private:stream" ) ) 2808 && IsReadOnly() ) 2809 { 2810 SetError(ERRCODE_SFX_DOCUMENTREADONLY, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); 2811 return sal_False; 2812 } 2813 2814 // this notification should be already sent by caller in sfxbasemodel 2815 // SFX_APP()->NotifyEvent(SfxEventHint( bSaveTo? SFX_EVENT_SAVETODOC : SFX_EVENT_SAVEASDOC,this)); 2816 2817 if( SFX_ITEM_SET != aParams->GetItemState(SID_UNPACK) && SvtSaveOptions().IsSaveUnpacked() ) 2818 aParams->Put( SfxBoolItem( SID_UNPACK, sal_False ) ); 2819 2820 ::rtl::OUString aTempFileURL; 2821 if ( IsDocShared() ) 2822 aTempFileURL = pMedium->GetURLObject().GetMainURL( INetURLObject::NO_DECODE ); 2823 2824 if ( PreDoSaveAs_Impl(aURL.GetMainURL( INetURLObject::NO_DECODE ),aFilterName,aParams)) 2825 { 2826 pImp->bWaitingForPicklist = sal_True; 2827 2828 // Daten am Medium updaten 2829 SfxItemSet *pSet = GetMedium()->GetItemSet(); 2830 pSet->ClearItem( SID_INTERACTIONHANDLER ); 2831 pSet->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL ); 2832 pSet->ClearItem( SID_STANDARD_DIR ); 2833 pSet->ClearItem( SID_PATH ); 2834 2835 if ( !bSaveTo ) 2836 { 2837 pSet->ClearItem( SID_REFERER ); 2838 pSet->ClearItem( SID_POSTDATA ); 2839 pSet->ClearItem( SID_TEMPLATE ); 2840 pSet->ClearItem( SID_DOC_READONLY ); 2841 pSet->ClearItem( SID_CONTENTTYPE ); 2842 pSet->ClearItem( SID_CHARSET ); 2843 pSet->ClearItem( SID_FILTER_NAME ); 2844 pSet->ClearItem( SID_OPTIONS ); 2845 //pSet->ClearItem( SID_FILE_FILTEROPTIONS ); 2846 pSet->ClearItem( SID_VERSION ); 2847 pSet->ClearItem( SID_EDITDOC ); 2848 pSet->ClearItem( SID_OVERWRITE ); 2849 pSet->ClearItem( SID_DEFAULTFILEPATH ); 2850 pSet->ClearItem( SID_DEFAULTFILENAME ); 2851 2852 SFX_ITEMSET_GET( (*aParams), pFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False ); 2853 if ( pFilterItem ) 2854 pSet->Put( *pFilterItem ); 2855 2856 SFX_ITEMSET_GET( (*aParams), pOptionsItem, SfxStringItem, SID_OPTIONS, sal_False ); 2857 if ( pOptionsItem ) 2858 pSet->Put( *pOptionsItem ); 2859 2860 SFX_ITEMSET_GET( (*aParams), pFilterOptItem, SfxStringItem, SID_FILE_FILTEROPTIONS, sal_False ); 2861 if ( pFilterOptItem ) 2862 pSet->Put( *pFilterOptItem ); 2863 2864 if ( IsDocShared() && aTempFileURL.getLength() ) 2865 { 2866 // this is a shared document that has to be disconnected from the old location 2867 FreeSharedFile( aTempFileURL ); 2868 2869 if ( pFilter->IsOwnFormat() 2870 && pFilter->UsesStorage() 2871 && pFilter->GetVersion() >= SOFFICE_FILEFORMAT_60 ) 2872 { 2873 // the target format is the own format 2874 // the target document must be shared 2875 SwitchToShared( sal_True, sal_False ); 2876 } 2877 } 2878 } 2879 2880 if ( bWasReadonly && !bSaveTo ) 2881 Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED) ); 2882 2883 return sal_True; 2884 } 2885 else 2886 return sal_False; 2887 } 2888 2889 //------------------------------------------------------------------------- 2890 2891 sal_Bool SfxObjectShell::PreDoSaveAs_Impl 2892 ( 2893 const String& rFileName, 2894 const String& aFilterName, 2895 SfxItemSet* pParams 2896 ) 2897 { 2898 // copy all items stored in the itemset of the current medium 2899 SfxAllItemSet* pMergedParams = new SfxAllItemSet( *pMedium->GetItemSet() ); 2900 2901 // in "SaveAs" title and password will be cleared ( maybe the new itemset contains new values, otherwise they will be empty ) 2902 pMergedParams->ClearItem( SID_PASSWORD ); 2903 pMergedParams->ClearItem( SID_DOCINFO_TITLE ); 2904 2905 pMergedParams->ClearItem( SID_INPUTSTREAM ); 2906 pMergedParams->ClearItem( SID_STREAM ); 2907 pMergedParams->ClearItem( SID_CONTENT ); 2908 pMergedParams->ClearItem( SID_DOC_READONLY ); 2909 pMergedParams->ClearItem( SID_DOC_BASEURL ); 2910 2911 pMergedParams->ClearItem( SID_REPAIRPACKAGE ); 2912 2913 // "SaveAs" will never store any version information - it's a complete new file ! 2914 pMergedParams->ClearItem( SID_VERSION ); 2915 2916 // merge the new parameters into the copy 2917 // all values present in both itemsets will be overwritten by the new parameters 2918 if( pParams ) 2919 pMergedParams->Put( *pParams ); 2920 //DELETEZ( pParams ); 2921 2922 #ifdef DBG_UTIL 2923 if ( pMergedParams->GetItemState( SID_DOC_SALVAGE) >= SFX_ITEM_SET ) 2924 DBG_ERROR("Salvage item present in Itemset, check the parameters!"); 2925 #endif 2926 2927 // should be unneccessary - too hot to handle! 2928 pMergedParams->ClearItem( SID_DOC_SALVAGE ); 2929 2930 // take over the new merged itemset 2931 pParams = pMergedParams; 2932 2933 // create a medium for the target URL 2934 SfxMedium *pNewFile = new SfxMedium( rFileName, STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC, sal_False, 0, pParams ); 2935 2936 // set filter; if no filter is given, take the default filter of the factory 2937 if ( aFilterName.Len() ) 2938 pNewFile->SetFilter( GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName ) ); 2939 else 2940 pNewFile->SetFilter( GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_IMPORT | SFX_FILTER_EXPORT ) ); 2941 2942 if ( pNewFile->GetErrorCode() != ERRCODE_NONE ) 2943 { 2944 // creating temporary file failed ( f.e. floppy disk not inserted! ) 2945 SetError( pNewFile->GetError(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2946 delete pNewFile; 2947 return sal_False; 2948 } 2949 2950 // check if a "SaveTo" is wanted, no "SaveAs" 2951 SFX_ITEMSET_ARG( pParams, pSaveToItem, SfxBoolItem, SID_SAVETO, sal_False ); 2952 sal_Bool bCopyTo = GetCreateMode() == SFX_CREATE_MODE_EMBEDDED || (pSaveToItem && pSaveToItem->GetValue()); 2953 2954 // distinguish between "Save" and "SaveAs" 2955 pImp->bIsSaving = sal_False; 2956 2957 // copy version list from "old" medium to target medium, so it can be used on saving 2958 if ( pImp->bPreserveVersions ) 2959 pNewFile->TransferVersionList_Impl( *pMedium ); 2960 2961 /* 2962 if ( GetMedium()->GetFilter() && ( GetMedium()->GetFilter()->GetFilterFlags() & SFX_FILTER_PACKED ) ) 2963 { 2964 SfxMedium *pMed = bCopyTo ? pMedium : pNewFile; 2965 pNewFile->SetError( GetMedium()->Unpack_Impl( pMed->GetPhysicalName() ) , ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2966 } 2967 */ 2968 // Save the document ( first as temporary file, then transfer to the target URL by committing the medium ) 2969 sal_Bool bOk = sal_False; 2970 if ( !pNewFile->GetErrorCode() && SaveTo_Impl( *pNewFile, NULL ) ) 2971 { 2972 bOk = sal_True; 2973 2974 // transfer a possible error from the medium to the document 2975 SetError( pNewFile->GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2976 2977 // notify the document that saving was done successfully 2978 if ( !bCopyTo ) 2979 { 2980 bOk = DoSaveCompleted( pNewFile ); 2981 } 2982 else 2983 bOk = DoSaveCompleted(0); 2984 2985 if( bOk ) 2986 { 2987 if( !bCopyTo ) 2988 SetModified( sal_False ); 2989 } 2990 else 2991 { 2992 // TODO/LATER: the code below must be dead since the storage commit makes all the stuff 2993 // and the DoSaveCompleted call should not be able to fail in general 2994 2995 DBG_ASSERT( !bCopyTo, "Error while reconnecting to medium, can't be handled!"); 2996 SetError( pNewFile->GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 2997 2998 if ( !bCopyTo ) 2999 { 3000 // reconnect to the old medium 3001 sal_Bool bRet( sal_False ); 3002 bRet = DoSaveCompleted( pMedium ); 3003 DBG_ASSERT( bRet, "Error in DoSaveCompleted, can't be handled!"); 3004 } 3005 3006 // TODO/LATER: disconnect the new file from the storage for the case when pure saving is done 3007 // if storing has corrupted the file, probably it must be restored either here or 3008 // by the storage 3009 DELETEZ( pNewFile ); 3010 } 3011 } 3012 else 3013 { 3014 SetError( pNewFile->GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); 3015 3016 // reconnect to the old storage 3017 DoSaveCompleted( 0 ); 3018 3019 DELETEZ( pNewFile ); 3020 } 3021 3022 if ( bCopyTo ) 3023 DELETEZ( pNewFile ); 3024 else if( !bOk ) 3025 SetModified( sal_True ); 3026 3027 return bOk; 3028 } 3029 3030 //------------------------------------------------------------------------ 3031 3032 sal_Bool SfxObjectShell::LoadFrom( SfxMedium& /*rMedium*/ ) 3033 { 3034 DBG_ERROR( "Base implementation, must not be called in general!" ); 3035 return sal_True; 3036 } 3037 3038 //------------------------------------------------------------------------- 3039 sal_Bool SfxObjectShell::IsInformationLost() 3040 { 3041 Sequence< PropertyValue > aProps = GetModel()->getArgs(); 3042 ::rtl::OUString aFilterName; 3043 ::rtl::OUString aPreusedFilterName; 3044 for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ ) 3045 { 3046 if ( aProps[nInd].Name.equalsAscii( "FilterName" ) ) 3047 aProps[nInd].Value >>= aFilterName; 3048 else if ( aProps[nInd].Name.equalsAscii( "PreusedFilterName" ) ) 3049 aProps[nInd].Value >>= aPreusedFilterName; 3050 } 3051 3052 // if current filter can lead to information loss and it was used 3053 // for the latest store then the user should be asked to store in own format 3054 if ( aFilterName.getLength() && aFilterName.equals( aPreusedFilterName ) ) 3055 { 3056 const SfxFilter *pFilt = GetMedium()->GetFilter(); 3057 DBG_ASSERT( pFilt && aFilterName.equals( pFilt->GetName() ), "MediaDescriptor contains wrong filter!\n" ); 3058 return ( pFilt && pFilt->IsAlienFormat() ); 3059 } 3060 3061 return sal_False; 3062 } 3063 3064 //------------------------------------------------------------------------- 3065 sal_Bool SfxObjectShell::CanReload_Impl() 3066 3067 /* [Beschreibung] 3068 3069 Interne Methode zum Feststellen, ob eine erneutes Laden des 3070 Dokuments (auch als RevertToSaved oder LastVersion bekannt) 3071 m"oglich ist. 3072 */ 3073 3074 { 3075 return pMedium && HasName() && !IsInModalMode() && !pImp->bForbidReload; 3076 } 3077 3078 //------------------------------------------------------------------------- 3079 3080 sal_uInt16 SfxObjectShell::GetHiddenInformationState( sal_uInt16 nStates ) 3081 { 3082 sal_uInt16 nState = 0; 3083 if ( nStates & HIDDENINFORMATION_DOCUMENTVERSIONS ) 3084 { 3085 if ( GetMedium()->GetVersionList().getLength() ) 3086 nState |= HIDDENINFORMATION_DOCUMENTVERSIONS; 3087 } 3088 3089 return nState; 3090 } 3091 3092 sal_Int16 SfxObjectShell::QueryHiddenInformation( HiddenWarningFact eFact, Window* pParent ) 3093 { 3094 sal_Int16 nRet = RET_YES; 3095 sal_uInt16 nResId = 0; 3096 SvtSecurityOptions::EOption eOption = static_cast< SvtSecurityOptions::EOption >( -1 ); 3097 3098 switch ( eFact ) 3099 { 3100 case WhenSaving : 3101 { 3102 nResId = STR_HIDDENINFO_CONTINUE_SAVING; 3103 eOption = SvtSecurityOptions::E_DOCWARN_SAVEORSEND; 3104 break; 3105 } 3106 case WhenPrinting : 3107 { 3108 nResId = STR_HIDDENINFO_CONTINUE_PRINTING; 3109 eOption = SvtSecurityOptions::E_DOCWARN_PRINT; 3110 break; 3111 } 3112 case WhenSigning : 3113 { 3114 nResId = STR_HIDDENINFO_CONTINUE_SIGNING; 3115 eOption = SvtSecurityOptions::E_DOCWARN_SIGNING; 3116 break; 3117 } 3118 case WhenCreatingPDF : 3119 { 3120 nResId = STR_HIDDENINFO_CONTINUE_CREATEPDF; 3121 eOption = SvtSecurityOptions::E_DOCWARN_CREATEPDF; 3122 break; 3123 } 3124 default: 3125 { 3126 DBG_ERRORFILE( "SfxObjectShell::DetectHiddenInformation(): what fact?" ); 3127 } 3128 } 3129 3130 if ( eOption != -1 && SvtSecurityOptions().IsOptionSet( eOption ) ) 3131 { 3132 String sMessage( SfxResId( STR_HIDDENINFO_CONTAINS ) ); 3133 sal_uInt16 nWantedStates = HIDDENINFORMATION_RECORDEDCHANGES | HIDDENINFORMATION_NOTES; 3134 if ( eFact != WhenPrinting ) 3135 nWantedStates |= HIDDENINFORMATION_DOCUMENTVERSIONS; 3136 sal_uInt16 nStates = GetHiddenInformationState( nWantedStates ); 3137 bool bWarning = false; 3138 3139 if ( ( nStates & HIDDENINFORMATION_RECORDEDCHANGES ) == HIDDENINFORMATION_RECORDEDCHANGES ) 3140 { 3141 sMessage += String( SfxResId( STR_HIDDENINFO_RECORDCHANGES ) ); 3142 sMessage += '\n'; 3143 bWarning = true; 3144 } 3145 if ( ( nStates & HIDDENINFORMATION_NOTES ) == HIDDENINFORMATION_NOTES ) 3146 { 3147 sMessage += String( SfxResId( STR_HIDDENINFO_NOTES ) ); 3148 sMessage += '\n'; 3149 bWarning = true; 3150 } 3151 if ( ( nStates & HIDDENINFORMATION_DOCUMENTVERSIONS ) == HIDDENINFORMATION_DOCUMENTVERSIONS ) 3152 { 3153 sMessage += String( SfxResId( STR_HIDDENINFO_DOCVERSIONS ) ); 3154 sMessage += '\n'; 3155 bWarning = true; 3156 } 3157 3158 if ( bWarning ) 3159 { 3160 sMessage += '\n'; 3161 sMessage += String( SfxResId( nResId ) ); 3162 WarningBox aWBox( pParent, WB_YES_NO | WB_DEF_NO, sMessage ); 3163 nRet = aWBox.Execute(); 3164 } 3165 } 3166 3167 return nRet; 3168 } 3169 3170 sal_Bool SfxObjectShell::HasSecurityOptOpenReadOnly() const 3171 { 3172 return sal_True; 3173 } 3174 3175 sal_Bool SfxObjectShell::IsSecurityOptOpenReadOnly() const 3176 { 3177 return IsLoadReadonly(); 3178 } 3179 3180 void SfxObjectShell::SetSecurityOptOpenReadOnly( sal_Bool _b ) 3181 { 3182 SetLoadReadonly( _b ); 3183 } 3184 3185 sal_Bool SfxObjectShell::LoadOwnFormat( SfxMedium& rMedium ) 3186 { 3187 RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "PERFORMANCE SfxObjectShell::LoadOwnFormat" ); 3188 if( RTL_LOGFILE_HASLOGFILE() ) 3189 { 3190 ByteString aString( rMedium.GetName(), RTL_TEXTENCODING_ASCII_US ); 3191 RTL_LOGFILE_PRODUCT_CONTEXT_TRACE1( aLog, "loading \"%s\"", aString.GetBuffer() ); 3192 } 3193 3194 uno::Reference< embed::XStorage > xStorage = rMedium.GetStorage(); 3195 if ( xStorage.is() ) 3196 { 3197 // Password 3198 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pPasswdItem, SfxStringItem, SID_PASSWORD, sal_False ); 3199 if ( pPasswdItem || ERRCODE_IO_ABORT != CheckPasswd_Impl( this, SFX_APP()->GetPool(), pMedium ) ) 3200 { 3201 uno::Sequence< beans::NamedValue > aEncryptionData; 3202 if ( GetEncryptionData_Impl(pMedium->GetItemSet(), aEncryptionData) ) 3203 { 3204 try 3205 { 3206 // the following code must throw an exception in case of failure 3207 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xStorage, aEncryptionData ); 3208 } 3209 catch( uno::Exception& ) 3210 { 3211 // TODO/LATER: handle the error code 3212 } 3213 } 3214 3215 // load document 3216 return Load( rMedium ); 3217 } 3218 return sal_False; 3219 } 3220 else 3221 return sal_False; 3222 } 3223 3224 sal_Bool SfxObjectShell::SaveAsOwnFormat( SfxMedium& rMedium ) 3225 { 3226 uno::Reference< embed::XStorage > xStorage = rMedium.GetStorage(); 3227 if( xStorage.is() ) 3228 { 3229 sal_Int32 nVersion = rMedium.GetFilter()->GetVersion(); 3230 3231 // OASIS templates have own mediatypes ( SO7 also actually, but it is to late to use them here ) 3232 sal_Bool bTemplate = ( rMedium.GetFilter()->IsOwnTemplateFormat() && nVersion > SOFFICE_FILEFORMAT_60 ); 3233 3234 SetupStorage( xStorage, nVersion, bTemplate ); 3235 3236 if ( HasBasic() ) 3237 { 3238 // Initialize Basic 3239 GetBasicManager(); 3240 3241 // Save dialog/script container 3242 pImp->pBasicManager->storeLibrariesToStorage( xStorage ); 3243 } 3244 3245 return SaveAs( rMedium ); 3246 } 3247 else return sal_False; 3248 } 3249 3250 uno::Reference< embed::XStorage > SfxObjectShell::GetStorage() 3251 { 3252 if ( !pImp->m_xDocStorage.is() ) 3253 { 3254 OSL_ENSURE( pImp->m_bCreateTempStor, "The storage must exist already!\n" ); 3255 try { 3256 // no notification is required the storage is set the first time 3257 pImp->m_xDocStorage = ::comphelper::OStorageHelper::GetTemporaryStorage(); 3258 OSL_ENSURE( pImp->m_xDocStorage.is(), "The method must either return storage or throw an exception!" ); 3259 3260 SetupStorage( pImp->m_xDocStorage, SOFFICE_FILEFORMAT_CURRENT, sal_False ); 3261 pImp->m_bCreateTempStor = sal_False; 3262 SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED, GlobalEventConfig::GetEventName(STR_EVENT_STORAGECHANGED), this ) ); 3263 } 3264 catch( uno::Exception& ) 3265 { 3266 // TODO/LATER: error handling? 3267 } 3268 } 3269 3270 OSL_ENSURE( pImp->m_xDocStorage.is(), "The document storage must be created!" ); 3271 return pImp->m_xDocStorage; 3272 } 3273 3274 3275 sal_Bool SfxObjectShell::SaveChildren( sal_Bool bObjectsOnly ) 3276 { 3277 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::SaveChildren" ); 3278 3279 sal_Bool bResult = sal_True; 3280 if ( pImp->mpObjectContainer ) 3281 { 3282 sal_Bool bOasis = ( SotStorage::GetVersion( GetStorage() ) > SOFFICE_FILEFORMAT_60 ); 3283 GetEmbeddedObjectContainer().StoreChildren(bOasis,bObjectsOnly); 3284 } 3285 3286 return bResult; 3287 } 3288 3289 sal_Bool SfxObjectShell::SaveAsChildren( SfxMedium& rMedium ) 3290 { 3291 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::SaveAsChildren" ); 3292 3293 sal_Bool bResult = sal_True; 3294 3295 uno::Reference < embed::XStorage > xStorage = rMedium.GetStorage(); 3296 if ( !xStorage.is() ) 3297 return sal_False; 3298 3299 if ( xStorage == GetStorage() ) 3300 return SaveChildren(); 3301 3302 sal_Bool bOasis = sal_True; 3303 if ( pImp->mpObjectContainer ) 3304 { 3305 bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 ); 3306 GetEmbeddedObjectContainer().StoreAsChildren(bOasis,SFX_CREATE_MODE_EMBEDDED == eCreateMode,xStorage); 3307 } 3308 3309 if ( bResult ) 3310 bResult = CopyStoragesOfUnknownMediaType( GetStorage(), xStorage ); 3311 3312 return bResult; 3313 } 3314 3315 sal_Bool SfxObjectShell::SaveCompletedChildren( sal_Bool bSuccess ) 3316 { 3317 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::SaveCompletedChildren" ); 3318 3319 sal_Bool bResult = sal_True; 3320 3321 if ( pImp->mpObjectContainer ) 3322 { 3323 uno::Sequence < ::rtl::OUString > aNames = GetEmbeddedObjectContainer().GetObjectNames(); 3324 for ( sal_Int32 n=0; n<aNames.getLength(); n++ ) 3325 { 3326 uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObjectContainer().GetEmbeddedObject( aNames[n] ); 3327 OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" ); 3328 if ( xObj.is() ) 3329 { 3330 uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); 3331 if ( xPersist.is() ) 3332 { 3333 try 3334 { 3335 xPersist->saveCompleted( bSuccess ); 3336 } 3337 catch( uno::Exception& ) 3338 { 3339 // TODO/LATER: error handling 3340 bResult = sal_False; 3341 break; 3342 } 3343 } 3344 } 3345 } 3346 } 3347 3348 return bResult; 3349 } 3350 3351 sal_Bool SfxObjectShell::SwitchChildrenPersistance( const uno::Reference< embed::XStorage >& xStorage, 3352 sal_Bool bForceNonModified ) 3353 { 3354 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::SwitchChildrenPersistence" ); 3355 3356 if ( !xStorage.is() ) 3357 { 3358 // TODO/LATER: error handling 3359 return sal_False; 3360 } 3361 3362 sal_Bool bResult = sal_True; 3363 3364 if ( pImp->mpObjectContainer ) 3365 pImp->mpObjectContainer->SetPersistentEntries(xStorage,bForceNonModified); 3366 3367 return bResult; 3368 } 3369 3370 // Never call this method directly, always use the DoSaveCompleted call 3371 sal_Bool SfxObjectShell::SaveCompleted( const uno::Reference< embed::XStorage >& xStorage ) 3372 { 3373 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::SaveCompleted" ); 3374 3375 sal_Bool bResult = sal_False; 3376 sal_Bool bSendNotification = sal_False; 3377 uno::Reference< embed::XStorage > xOldStorageHolder; 3378 3379 #ifdef DBG_UTIL 3380 // check for wrong creation of object container 3381 sal_Bool bHasContainer = ( pImp->mpObjectContainer != 0 ); 3382 #endif 3383 3384 if ( !xStorage.is() || xStorage == GetStorage() ) 3385 { 3386 // no persistence change 3387 bResult = SaveCompletedChildren( sal_False ); 3388 } 3389 else 3390 { 3391 if ( pImp->mpObjectContainer ) 3392 GetEmbeddedObjectContainer().SwitchPersistence( xStorage ); 3393 3394 bResult = SwitchChildrenPersistance( xStorage, sal_True ); 3395 } 3396 3397 if ( bResult ) 3398 { 3399 if ( xStorage.is() && pImp->m_xDocStorage != xStorage ) 3400 { 3401 // make sure that until the storage is assigned the object container is not created by accident! 3402 DBG_ASSERT( bHasContainer == (pImp->mpObjectContainer != 0), "Wrong storage in object container!" ); 3403 xOldStorageHolder = pImp->m_xDocStorage; 3404 pImp->m_xDocStorage = xStorage; 3405 bSendNotification = sal_True; 3406 3407 if ( IsEnableSetModified() ) 3408 SetModified( sal_False ); 3409 } 3410 } 3411 else 3412 { 3413 if ( pImp->mpObjectContainer ) 3414 GetEmbeddedObjectContainer().SwitchPersistence( pImp->m_xDocStorage ); 3415 3416 // let already successfully connected objects be switched back 3417 SwitchChildrenPersistance( pImp->m_xDocStorage, sal_True ); 3418 } 3419 3420 if ( bSendNotification ) 3421 { 3422 SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED, GlobalEventConfig::GetEventName(STR_EVENT_STORAGECHANGED), this ) ); 3423 } 3424 3425 return bResult; 3426 } 3427 3428 3429 sal_Bool StoragesOfUnknownMediaTypeAreCopied_Impl( const uno::Reference< embed::XStorage >& xSource, 3430 const uno::Reference< embed::XStorage >& xTarget ) 3431 { 3432 OSL_ENSURE( xSource.is() && xTarget.is(), "Source and/or target storages are not available!\n" ); 3433 if ( !xSource.is() || !xTarget.is() || xSource == xTarget ) 3434 return sal_True; 3435 3436 try 3437 { 3438 uno::Sequence< ::rtl::OUString > aSubElements = xSource->getElementNames(); 3439 for ( sal_Int32 nInd = 0; nInd < aSubElements.getLength(); nInd++ ) 3440 { 3441 if ( xSource->isStorageElement( aSubElements[nInd] ) ) 3442 { 3443 ::rtl::OUString aMediaType; 3444 ::rtl::OUString aMediaTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ); 3445 sal_Bool bGotMediaType = sal_False; 3446 3447 try 3448 { 3449 uno::Reference< embed::XOptimizedStorage > xOptStorage( xSource, uno::UNO_QUERY_THROW ); 3450 bGotMediaType = 3451 ( xOptStorage->getElementPropertyValue( aSubElements[nInd], aMediaTypePropName ) >>= aMediaType ); 3452 } 3453 catch( uno::Exception& ) 3454 {} 3455 3456 if ( !bGotMediaType ) 3457 { 3458 uno::Reference< embed::XStorage > xSubStorage; 3459 try { 3460 xSubStorage = xSource->openStorageElement( aSubElements[nInd], embed::ElementModes::READ ); 3461 } catch( uno::Exception& ) 3462 {} 3463 3464 if ( !xSubStorage.is() ) 3465 { 3466 xSubStorage = ::comphelper::OStorageHelper::GetTemporaryStorage(); 3467 xSource->copyStorageElementLastCommitTo( aSubElements[nInd], xSubStorage ); 3468 } 3469 3470 uno::Reference< beans::XPropertySet > xProps( xSubStorage, uno::UNO_QUERY_THROW ); 3471 bGotMediaType = ( xProps->getPropertyValue( aMediaTypePropName ) >>= aMediaType ); 3472 } 3473 3474 // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist 3475 // probably it should be placed in the MimeType-ClassID table or in standalone table 3476 if ( aMediaType.getLength() 3477 && aMediaType.compareToAscii( "application/vnd.sun.star.oleobject" ) != COMPARE_EQUAL ) 3478 { 3479 ::com::sun::star::datatransfer::DataFlavor aDataFlavor; 3480 aDataFlavor.MimeType = aMediaType; 3481 sal_uInt32 nFormat = SotExchange::GetFormat( aDataFlavor ); 3482 3483 switch ( nFormat ) 3484 { 3485 case SOT_FORMATSTR_ID_STARWRITER_60 : 3486 case SOT_FORMATSTR_ID_STARWRITERWEB_60 : 3487 case SOT_FORMATSTR_ID_STARWRITERGLOB_60 : 3488 case SOT_FORMATSTR_ID_STARDRAW_60 : 3489 case SOT_FORMATSTR_ID_STARIMPRESS_60 : 3490 case SOT_FORMATSTR_ID_STARCALC_60 : 3491 case SOT_FORMATSTR_ID_STARCHART_60 : 3492 case SOT_FORMATSTR_ID_STARMATH_60 : 3493 case SOT_FORMATSTR_ID_STARWRITER_8: 3494 case SOT_FORMATSTR_ID_STARWRITERWEB_8: 3495 case SOT_FORMATSTR_ID_STARWRITERGLOB_8: 3496 case SOT_FORMATSTR_ID_STARDRAW_8: 3497 case SOT_FORMATSTR_ID_STARIMPRESS_8: 3498 case SOT_FORMATSTR_ID_STARCALC_8: 3499 case SOT_FORMATSTR_ID_STARCHART_8: 3500 case SOT_FORMATSTR_ID_STARMATH_8: 3501 break; 3502 3503 default: 3504 { 3505 if ( !xTarget->hasByName( aSubElements[nInd] ) ) 3506 return sal_False; 3507 } 3508 } 3509 } 3510 } 3511 } 3512 } 3513 catch( uno::Exception& ) 3514 { 3515 OSL_ENSURE( sal_False, "Cant check storage consistency!\n" ); 3516 } 3517 3518 return sal_True; 3519 } 3520 3521 3522 sal_Bool SfxObjectShell::SwitchPersistance( const uno::Reference< embed::XStorage >& xStorage ) 3523 { 3524 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::SwitchPersistance" ); 3525 3526 sal_Bool bResult = sal_False; 3527 #ifdef DBG_UTIL 3528 // check for wrong creation of object container 3529 sal_Bool bHasContainer = ( pImp->mpObjectContainer != 0 ); 3530 #endif 3531 if ( xStorage.is() ) 3532 { 3533 if ( pImp->mpObjectContainer ) 3534 GetEmbeddedObjectContainer().SwitchPersistence( xStorage ); 3535 bResult = SwitchChildrenPersistance( xStorage ); 3536 3537 // TODO/LATER: substorages that have unknown mimetypes probably should be copied to the target storage here 3538 OSL_ENSURE( StoragesOfUnknownMediaTypeAreCopied_Impl( pImp->m_xDocStorage, xStorage ), 3539 "Some of substorages with unknown mimetypes is lost!" ); 3540 } 3541 3542 if ( bResult ) 3543 { 3544 // make sure that until the storage is assigned the object container is not created by accident! 3545 DBG_ASSERT( bHasContainer == (pImp->mpObjectContainer != 0), "Wrong storage in object container!" ); 3546 if ( pImp->m_xDocStorage != xStorage ) 3547 DoSaveCompleted( new SfxMedium( xStorage, GetMedium()->GetBaseURL() ) ); 3548 3549 if ( IsEnableSetModified() ) 3550 SetModified( sal_True ); // ??? 3551 } 3552 3553 return bResult; 3554 } 3555 3556 sal_Bool SfxObjectShell::CopyStoragesOfUnknownMediaType( const uno::Reference< embed::XStorage >& xSource, 3557 const uno::Reference< embed::XStorage >& xTarget ) 3558 { 3559 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::CopyStoragesOfUnknownMediaType" ); 3560 3561 // This method does not commit the target storage and should not do it 3562 sal_Bool bResult = sal_True; 3563 3564 try 3565 { 3566 uno::Sequence< ::rtl::OUString > aSubElements = xSource->getElementNames(); 3567 for ( sal_Int32 nInd = 0; nInd < aSubElements.getLength(); nInd++ ) 3568 { 3569 if ( aSubElements[nInd].equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Configurations" ) ) ) ) 3570 { 3571 // The workaround for compatibility with SO7, "Configurations" substorage must be preserved 3572 if ( xSource->isStorageElement( aSubElements[nInd] ) ) 3573 { 3574 OSL_ENSURE( !xTarget->hasByName( aSubElements[nInd] ), 3575 "The target storage is an output storage, the element should not exist in the target!\n" ); 3576 3577 xSource->copyElementTo( aSubElements[nInd], xTarget, aSubElements[nInd] ); 3578 } 3579 } 3580 else if ( xSource->isStorageElement( aSubElements[nInd] ) ) 3581 { 3582 ::rtl::OUString aMediaType; 3583 ::rtl::OUString aMediaTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ); 3584 sal_Bool bGotMediaType = sal_False; 3585 3586 try 3587 { 3588 uno::Reference< embed::XOptimizedStorage > xOptStorage( xSource, uno::UNO_QUERY_THROW ); 3589 bGotMediaType = 3590 ( xOptStorage->getElementPropertyValue( aSubElements[nInd], aMediaTypePropName ) >>= aMediaType ); 3591 } 3592 catch( uno::Exception& ) 3593 {} 3594 3595 if ( !bGotMediaType ) 3596 { 3597 uno::Reference< embed::XStorage > xSubStorage; 3598 try { 3599 xSubStorage = xSource->openStorageElement( aSubElements[nInd], embed::ElementModes::READ ); 3600 } catch( uno::Exception& ) 3601 {} 3602 3603 if ( !xSubStorage.is() ) 3604 { 3605 // TODO/LATER: as optimization in future a substorage of target storage could be used 3606 // instead of the temporary storage; this substorage should be removed later 3607 // if the MimeType is wrong 3608 xSubStorage = ::comphelper::OStorageHelper::GetTemporaryStorage(); 3609 xSource->copyStorageElementLastCommitTo( aSubElements[nInd], xSubStorage ); 3610 } 3611 3612 uno::Reference< beans::XPropertySet > xProps( xSubStorage, uno::UNO_QUERY_THROW ); 3613 bGotMediaType = ( xProps->getPropertyValue( aMediaTypePropName ) >>= aMediaType ); 3614 } 3615 3616 // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist 3617 // probably it should be placed in the MimeType-ClassID table or in standalone table 3618 if ( aMediaType.getLength() 3619 && aMediaType.compareToAscii( "application/vnd.sun.star.oleobject" ) != COMPARE_EQUAL ) 3620 { 3621 ::com::sun::star::datatransfer::DataFlavor aDataFlavor; 3622 aDataFlavor.MimeType = aMediaType; 3623 sal_uInt32 nFormat = SotExchange::GetFormat( aDataFlavor ); 3624 3625 switch ( nFormat ) 3626 { 3627 case SOT_FORMATSTR_ID_STARWRITER_60 : 3628 case SOT_FORMATSTR_ID_STARWRITERWEB_60 : 3629 case SOT_FORMATSTR_ID_STARWRITERGLOB_60 : 3630 case SOT_FORMATSTR_ID_STARDRAW_60 : 3631 case SOT_FORMATSTR_ID_STARIMPRESS_60 : 3632 case SOT_FORMATSTR_ID_STARCALC_60 : 3633 case SOT_FORMATSTR_ID_STARCHART_60 : 3634 case SOT_FORMATSTR_ID_STARMATH_60 : 3635 case SOT_FORMATSTR_ID_STARWRITER_8: 3636 case SOT_FORMATSTR_ID_STARWRITERWEB_8: 3637 case SOT_FORMATSTR_ID_STARWRITERGLOB_8: 3638 case SOT_FORMATSTR_ID_STARDRAW_8: 3639 case SOT_FORMATSTR_ID_STARIMPRESS_8: 3640 case SOT_FORMATSTR_ID_STARCALC_8: 3641 case SOT_FORMATSTR_ID_STARCHART_8: 3642 case SOT_FORMATSTR_ID_STARMATH_8: 3643 break; 3644 3645 default: 3646 { 3647 OSL_ENSURE( 3648 aSubElements[nInd].equalsAscii( "Configurations2" ) || !xTarget->hasByName( aSubElements[nInd] ), 3649 "The target storage is an output storage, the element should not exist in the target!\n" ); 3650 3651 if ( !xTarget->hasByName( aSubElements[nInd] ) ) 3652 { 3653 xSource->copyElementTo( aSubElements[nInd], xTarget, aSubElements[nInd] ); 3654 } 3655 } 3656 } 3657 } 3658 } 3659 } 3660 } 3661 catch( uno::Exception& ) 3662 { 3663 bResult = sal_False; 3664 // TODO/LATER: a specific error could be provided 3665 } 3666 3667 return bResult; 3668 } 3669 3670 sal_Bool SfxObjectShell::GenerateAndStoreThumbnail( sal_Bool bEncrypted, 3671 sal_Bool bSigned, 3672 sal_Bool bIsTemplate, 3673 const uno::Reference< embed::XStorage >& xStor ) 3674 { 3675 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxObjectShell::GenerateAndStoreThumbnail" ); 3676 3677 sal_Bool bResult = sal_False; 3678 3679 try { 3680 uno::Reference< embed::XStorage > xThumbnailStor = 3681 xStor->openStorageElement( ::rtl::OUString::createFromAscii( "Thumbnails" ), 3682 embed::ElementModes::READWRITE ); 3683 if ( xThumbnailStor.is() ) 3684 { 3685 uno::Reference< io::XStream > xStream = xThumbnailStor->openStreamElement( 3686 ::rtl::OUString::createFromAscii( "thumbnail.png" ), 3687 embed::ElementModes::READWRITE ); 3688 3689 if ( xStream.is() && WriteThumbnail( bEncrypted, bSigned, bIsTemplate, xStream ) ) 3690 { 3691 uno::Reference< embed::XTransactedObject > xTransact( xThumbnailStor, uno::UNO_QUERY_THROW ); 3692 xTransact->commit(); 3693 bResult = sal_True; 3694 } 3695 } 3696 } 3697 catch( uno::Exception& ) 3698 { 3699 } 3700 3701 return bResult; 3702 } 3703 3704 sal_Bool SfxObjectShell::WriteThumbnail( sal_Bool bEncrypted, 3705 sal_Bool bSigned, 3706 sal_Bool bIsTemplate, 3707 const uno::Reference< io::XStream >& xStream ) 3708 { 3709 sal_Bool bResult = sal_False; 3710 3711 if ( xStream.is() ) 3712 { 3713 try { 3714 uno::Reference< io::XTruncate > xTruncate( xStream->getOutputStream(), uno::UNO_QUERY_THROW ); 3715 xTruncate->truncate(); 3716 3717 if ( bEncrypted ) 3718 { 3719 sal_uInt16 nResID = GraphicHelper::getThumbnailReplacementIDByFactoryName_Impl( 3720 ::rtl::OUString::createFromAscii( GetFactory().GetShortName() ), 3721 bIsTemplate ); 3722 if ( nResID ) 3723 { 3724 if ( !bSigned ) 3725 { 3726 bResult = GraphicHelper::getThumbnailReplacement_Impl( nResID, xStream ); 3727 } 3728 else 3729 { 3730 // retrieve the bitmap and write a signature bitmap over it 3731 SfxResId aResId( nResID ); 3732 BitmapEx aThumbBitmap( aResId ); 3733 bResult = GraphicHelper::getSignedThumbnailFormatFromBitmap_Impl( aThumbBitmap, xStream ); 3734 } 3735 } 3736 } 3737 else 3738 { 3739 ::boost::shared_ptr<GDIMetaFile> pMetaFile = 3740 GetPreviewMetaFile( sal_False ); 3741 if ( pMetaFile ) 3742 { 3743 bResult = GraphicHelper::getThumbnailFormatFromGDI_Impl( 3744 pMetaFile.get(), bSigned, xStream ); 3745 } 3746 } 3747 } 3748 catch( uno::Exception& ) 3749 {} 3750 } 3751 3752 return bResult; 3753 } 3754 3755 void SfxObjectShell::UpdateLinks() 3756 { 3757 } 3758 3759 sal_Bool SfxObjectShell::QuerySaveSizeExceededModules_Impl( const uno::Reference< task::XInteractionHandler >& xHandler ) 3760 { 3761 if ( !HasBasic() ) 3762 return sal_True; 3763 3764 if ( !pImp->pBasicManager->isValid() ) 3765 GetBasicManager(); 3766 uno::Sequence< rtl::OUString > sModules; 3767 if ( xHandler.is() ) 3768 { 3769 if( pImp->pBasicManager->LegacyPsswdBinaryLimitExceeded( sModules ) ) 3770 { 3771 ModuleSizeExceeded* pReq = new ModuleSizeExceeded( sModules ); 3772 uno::Reference< task::XInteractionRequest > xReq( pReq ); 3773 xHandler->handle( xReq ); 3774 return pReq->isApprove(); 3775 } 3776 } 3777 // No interaction handler, default is to continue to save 3778 return sal_True; 3779 } 3780 // ----------------------------------------------------------------------------- 3781 uno::Reference< task::XInteractionHandler > SfxObjectShell::getInteractionHandler() const 3782 { 3783 uno::Reference< task::XInteractionHandler > xRet; 3784 if ( GetMedium() ) 3785 xRet = GetMedium()->GetInteractionHandler(); 3786 return xRet; 3787 } 3788