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