1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sfx2.hxx" 30 31 #include <sot/storage.hxx> 32 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> 33 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> 34 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> 35 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> 36 #include <com/sun/star/ui/dialogs/XControlAccess.hpp> 37 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 38 #include <com/sun/star/beans/XPropertyAccess.hpp> 39 #include <com/sun/star/beans/XPropertySet.hpp> 40 #include <com/sun/star/beans/PropertyValue.hpp> 41 #include <com/sun/star/container/XNameAccess.hpp> 42 #include <com/sun/star/document/XExporter.hpp> 43 #include <com/sun/star/task/XInteractionHandler.hpp> 44 #include <com/sun/star/task/XStatusIndicator.hpp> 45 #include <com/sun/star/task/XStatusIndicatorFactory.hpp> 46 #include <com/sun/star/frame/XDocumentTemplates.hpp> 47 #include <com/sun/star/frame/XStorable.hpp> 48 #include <comphelper/processfactory.hxx> 49 #include <com/sun/star/security/CertificateValidity.hpp> 50 51 #include <com/sun/star/security/DocumentSignatureInformation.hpp> 52 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp> 53 #include <tools/urlobj.hxx> 54 #include <svl/whiter.hxx> 55 #include <vcl/msgbox.hxx> 56 #include <svl/intitem.hxx> 57 #include <svl/eitem.hxx> 58 #include <vcl/wrkwin.hxx> 59 #include <svtools/sfxecode.hxx> 60 #include <svtools/ehdl.hxx> 61 62 #include <comphelper/string.hxx> 63 #include <basic/sbx.hxx> 64 #include <unotools/pathoptions.hxx> 65 #include <unotools/useroptions.hxx> 66 #include <svtools/asynclink.hxx> 67 #include <unotools/saveopt.hxx> 68 #include <comphelper/documentconstants.hxx> 69 70 #include <sfx2/app.hxx> 71 #include <sfx2/signaturestate.hxx> 72 #include "sfx2/sfxresid.hxx" 73 #include <sfx2/event.hxx> 74 #include <sfx2/request.hxx> 75 #include <sfx2/printer.hxx> 76 #include <sfx2/viewsh.hxx> 77 #include <sfx2/doctdlg.hxx> 78 #include <sfx2/docfilt.hxx> 79 #include <sfx2/docfile.hxx> 80 #include <sfx2/dispatch.hxx> 81 #include <sfx2/dinfdlg.hxx> 82 #include <sfx2/objitem.hxx> 83 #include <sfx2/objsh.hxx> 84 #include "objshimp.hxx" 85 #include "sfxtypes.hxx" 86 //#include "interno.hxx" 87 #include <sfx2/module.hxx> 88 #include <sfx2/viewfrm.hxx> 89 #include "versdlg.hxx" 90 #include "doc.hrc" 91 #include <sfx2/docfac.hxx> 92 #include <sfx2/fcontnr.hxx> 93 #include <sfx2/filedlghelper.hxx> 94 #include "sfx2/sfxhelp.hxx" 95 #include <sfx2/msgpool.hxx> 96 #include <sfx2/objface.hxx> 97 98 #include "../appl/app.hrc" 99 #include <com/sun/star/document/XDocumentSubStorageSupplier.hpp> 100 #include <com/sun/star/embed/XTransactedObject.hpp> 101 #include <com/sun/star/util/XCloneable.hpp> 102 #include <com/sun/star/document/XDocumentProperties.hpp> 103 104 #include "helpid.hrc" 105 106 #include "guisaveas.hxx" 107 108 using namespace ::com::sun::star; 109 using namespace ::com::sun::star::lang; 110 using namespace ::com::sun::star::uno; 111 using namespace ::com::sun::star::ui::dialogs; 112 using namespace ::com::sun::star::awt; 113 using namespace ::com::sun::star::container; 114 using namespace ::com::sun::star::beans; 115 using namespace ::com::sun::star::document; 116 using namespace ::com::sun::star::task; 117 118 //==================================================================== 119 120 class SfxSaveAsContext_Impl 121 { 122 String& _rNewNameVar; 123 String _aNewName; 124 125 public: 126 SfxSaveAsContext_Impl( String &rNewNameVar, 127 const String &rNewName ) 128 : _rNewNameVar( rNewNameVar ), 129 _aNewName( rNewName ) 130 { rNewNameVar = rNewName; } 131 ~SfxSaveAsContext_Impl() 132 { _rNewNameVar.Erase(); } 133 }; 134 135 //==================================================================== 136 137 #define SfxObjectShell 138 #include "sfxslots.hxx" 139 140 //========================================================================= 141 142 143 144 SFX_IMPL_INTERFACE(SfxObjectShell,SfxShell,SfxResId(0)) 145 { 146 } 147 148 //========================================================================= 149 150 class SfxClosePreventer_Impl : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XCloseListener > 151 { 152 sal_Bool m_bGotOwnership; 153 sal_Bool m_bPreventClose; 154 155 public: 156 SfxClosePreventer_Impl(); 157 158 sal_Bool HasOwnership() { return m_bGotOwnership; } 159 160 void SetPreventClose( sal_Bool bPrevent ) { m_bPreventClose = bPrevent; } 161 162 virtual void SAL_CALL queryClosing( const lang::EventObject& aEvent, sal_Bool bDeliverOwnership ) 163 throw ( uno::RuntimeException, util::CloseVetoException ); 164 165 virtual void SAL_CALL notifyClosing( const lang::EventObject& aEvent ) throw ( uno::RuntimeException ) ; 166 167 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw ( uno::RuntimeException ) ; 168 169 } ; 170 171 SfxClosePreventer_Impl::SfxClosePreventer_Impl() 172 : m_bGotOwnership( sal_False ) 173 , m_bPreventClose( sal_True ) 174 { 175 } 176 177 void SAL_CALL SfxClosePreventer_Impl::queryClosing( const lang::EventObject&, sal_Bool bDeliverOwnership ) 178 throw ( uno::RuntimeException, util::CloseVetoException ) 179 { 180 if ( m_bPreventClose ) 181 { 182 if ( !m_bGotOwnership ) 183 m_bGotOwnership = bDeliverOwnership; 184 185 throw util::CloseVetoException(); 186 } 187 } 188 189 void SAL_CALL SfxClosePreventer_Impl::notifyClosing( const lang::EventObject& ) throw ( uno::RuntimeException ) 190 {} 191 192 void SAL_CALL SfxClosePreventer_Impl::disposing( const lang::EventObject& ) throw ( uno::RuntimeException ) 193 {} 194 195 //========================================================================= 196 class SfxInstanceCloseGuard_Impl 197 { 198 SfxClosePreventer_Impl* m_pPreventer; 199 uno::Reference< util::XCloseListener > m_xPreventer; 200 uno::Reference< util::XCloseable > m_xCloseable; 201 202 public: 203 SfxInstanceCloseGuard_Impl() 204 : m_pPreventer( NULL ) 205 {} 206 207 ~SfxInstanceCloseGuard_Impl(); 208 209 sal_Bool Init_Impl( const uno::Reference< util::XCloseable >& xCloseable ); 210 }; 211 212 sal_Bool SfxInstanceCloseGuard_Impl::Init_Impl( const uno::Reference< util::XCloseable >& xCloseable ) 213 { 214 sal_Bool bResult = sal_False; 215 216 // do not allow reinit after the successful init 217 if ( xCloseable.is() && !m_xCloseable.is() ) 218 { 219 try 220 { 221 m_pPreventer = new SfxClosePreventer_Impl(); 222 m_xPreventer = uno::Reference< util::XCloseListener >( m_pPreventer ); 223 xCloseable->addCloseListener( m_xPreventer ); 224 m_xCloseable = xCloseable; 225 bResult = sal_True; 226 } 227 catch( uno::Exception& ) 228 { 229 OSL_ENSURE( sal_False, "Could not register close listener!\n" ); 230 } 231 } 232 233 return bResult; 234 } 235 236 SfxInstanceCloseGuard_Impl::~SfxInstanceCloseGuard_Impl() 237 { 238 if ( m_xCloseable.is() && m_xPreventer.is() ) 239 { 240 try 241 { 242 m_xCloseable->removeCloseListener( m_xPreventer ); 243 } 244 catch( uno::Exception& ) 245 { 246 } 247 248 try 249 { 250 if ( m_pPreventer ) 251 { 252 m_pPreventer->SetPreventClose( sal_False ); 253 254 if ( m_pPreventer->HasOwnership() ) 255 m_xCloseable->close( sal_True ); // TODO: do it asynchronously 256 } 257 } 258 catch( uno::Exception& ) 259 { 260 } 261 } 262 } 263 264 //========================================================================= 265 266 void SfxObjectShell::PrintExec_Impl(SfxRequest &rReq) 267 { 268 SfxViewFrame *pFrame = SfxViewFrame::GetFirst(this); 269 if ( pFrame ) 270 { 271 rReq.SetSlot( SID_PRINTDOC ); 272 pFrame->GetViewShell()->ExecuteSlot(rReq); 273 } 274 } 275 276 //-------------------------------------------------------------------- 277 278 void SfxObjectShell::PrintState_Impl(SfxItemSet &rSet) 279 { 280 bool bPrinting = false; 281 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this ); 282 if ( pFrame ) 283 { 284 SfxPrinter *pPrinter = pFrame->GetViewShell()->GetPrinter(); 285 bPrinting = pPrinter && pPrinter->IsPrinting(); 286 } 287 rSet.Put( SfxBoolItem( SID_PRINTOUT, bPrinting ) ); 288 } 289 290 //-------------------------------------------------------------------- 291 292 sal_Bool SfxObjectShell::APISaveAs_Impl 293 ( 294 const String& aFileName, 295 SfxItemSet* aParams 296 ) 297 { 298 sal_Bool bOk = sal_False; 299 300 {DBG_CHKTHIS(SfxObjectShell, 0);} 301 302 if ( GetMedium() ) 303 { 304 String aFilterName; 305 SFX_ITEMSET_ARG( aParams, pFilterNameItem, SfxStringItem, SID_FILTER_NAME, sal_False ); 306 if( pFilterNameItem ) 307 { 308 aFilterName = pFilterNameItem->GetValue(); 309 } 310 else 311 { 312 SFX_ITEMSET_ARG( aParams, pContentTypeItem, SfxStringItem, SID_CONTENTTYPE, sal_False ); 313 if ( pContentTypeItem ) 314 { 315 const SfxFilter* pFilter = SfxFilterMatcher( String::CreateFromAscii(GetFactory().GetShortName()) ).GetFilter4Mime( pContentTypeItem->GetValue(), SFX_FILTER_EXPORT ); 316 if ( pFilter ) 317 aFilterName = pFilter->GetName(); 318 } 319 } 320 321 // in case no filter defined use default one 322 if( !aFilterName.Len() ) 323 { 324 const SfxFilter* pFilt = SfxFilter::GetDefaultFilterFromFactory(GetFactory().GetFactoryName()); 325 326 DBG_ASSERT( pFilt, "No default filter!\n" ); 327 if( pFilt ) 328 aFilterName = pFilt->GetFilterName(); 329 330 aParams->Put(SfxStringItem( SID_FILTER_NAME, aFilterName)); 331 } 332 333 334 { 335 SfxObjectShellRef xLock( this ); // ??? 336 337 // use the title that is provided in the media descriptor 338 SFX_ITEMSET_ARG( aParams, pDocTitleItem, SfxStringItem, SID_DOCINFO_TITLE, sal_False ); 339 if ( pDocTitleItem ) 340 getDocProperties()->setTitle( pDocTitleItem->GetValue() ); 341 342 bOk = CommonSaveAs_Impl( INetURLObject(aFileName), aFilterName, 343 aParams ); 344 345 } 346 347 // prevent picklist-entry 348 GetMedium()->SetUpdatePickList( sal_False ); 349 } 350 351 return bOk; 352 } 353 354 //-------------------------------------------------------------------- 355 356 void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) 357 { 358 {DBG_CHKTHIS(SfxObjectShell, 0);} 359 360 sal_uInt16 nId = rReq.GetSlot(); 361 362 if( SID_SIGNATURE == nId || SID_MACRO_SIGNATURE == nId ) 363 { 364 if ( QueryHiddenInformation( WhenSigning, NULL ) == RET_YES ) 365 ( SID_SIGNATURE == nId ) ? SignDocumentContent() : SignScriptingContent(); 366 return; 367 } 368 369 if ( !GetMedium() && nId != SID_CLOSEDOC ) 370 { 371 rReq.Ignore(); 372 return; 373 } 374 375 // this guard is created here to have it destruction at the end of the method 376 SfxInstanceCloseGuard_Impl aModelGuard; 377 378 sal_Bool bIsPDFExport = sal_False; 379 switch(nId) 380 { 381 case SID_VERSION: 382 { 383 SfxViewFrame* pFrame = GetFrame(); 384 if ( !pFrame ) 385 pFrame = SfxViewFrame::GetFirst( this ); 386 if ( !pFrame ) 387 return; 388 389 if ( pFrame->GetFrame().GetParentFrame() ) 390 { 391 pFrame->GetTopViewFrame()->GetObjectShell()->ExecuteSlot( rReq ); 392 return; 393 } 394 395 if ( !IsOwnStorageFormat_Impl( *GetMedium() ) ) 396 return; 397 398 SfxVersionDialog *pDlg = new SfxVersionDialog( pFrame, IsSaveVersionOnClose() ); 399 pDlg->Execute(); 400 SetSaveVersionOnClose( pDlg->IsSaveVersionOnClose() ); 401 delete pDlg; 402 rReq.Done(); 403 return; 404 } 405 406 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 407 case SID_DOCINFO: 408 { 409 SFX_REQUEST_ARG(rReq, pDocInfItem, SfxDocumentInfoItem, SID_DOCINFO, sal_False); 410 if ( pDocInfItem ) 411 { 412 // parameter, e.g. from replayed macro 413 pDocInfItem->UpdateDocumentInfo(getDocProperties(), true); 414 SetUseUserData( pDocInfItem->IsUseUserData() ); 415 } 416 else 417 { 418 // no argument containing DocInfo; check optional arguments 419 sal_Bool bReadOnly = IsReadOnly(); 420 SFX_REQUEST_ARG(rReq, pROItem, SfxBoolItem, SID_DOC_READONLY, sal_False); 421 if ( pROItem ) 422 // override readonly attribute of document 423 // e.g. if a readonly document is saved elsewhere and user asks for editing DocInfo before 424 bReadOnly = pROItem->GetValue(); 425 426 // collect data for dialog 427 String aURL, aTitle; 428 if ( HasName() ) 429 { 430 aURL = GetMedium()->GetName(); 431 aTitle = GetTitle(); 432 } 433 else 434 { 435 aURL = DEFINE_CONST_UNICODE( "private:factory/" ); 436 aURL += String::CreateFromAscii( GetFactory().GetShortName() ); 437 438 aTitle = GetTitle(); 439 } 440 441 SfxDocumentInfoItem aDocInfoItem( aURL, getDocProperties(), 442 IsUseUserData() ); 443 if ( !GetSlotState( SID_DOCTEMPLATE ) ) 444 // templates not supported 445 aDocInfoItem.SetTemplate(sal_False); 446 447 SfxItemSet aSet(GetPool(), SID_DOCINFO, SID_DOCINFO, SID_DOC_READONLY, SID_DOC_READONLY, 448 SID_EXPLORER_PROPS_START, SID_EXPLORER_PROPS_START, SID_BASEURL, SID_BASEURL, 449 0L ); 450 aSet.Put( aDocInfoItem ); 451 aSet.Put( SfxBoolItem( SID_DOC_READONLY, bReadOnly ) ); 452 aSet.Put( SfxStringItem( SID_EXPLORER_PROPS_START, aTitle ) ); 453 aSet.Put( SfxStringItem( SID_BASEURL, GetMedium()->GetBaseURL() ) ); 454 455 // creating dialog is done via virtual method; application will add its own statistics page 456 SfxDocumentInfoDialog *pDlg = CreateDocumentInfoDialog(0, aSet); 457 if ( RET_OK == pDlg->Execute() ) 458 { 459 SFX_ITEMSET_ARG( pDlg->GetOutputItemSet(), pDocInfoItem, SfxDocumentInfoItem, SID_DOCINFO, sal_False); 460 if ( pDocInfoItem ) 461 { 462 // user has done some changes to DocumentInfo 463 pDocInfoItem->UpdateDocumentInfo(getDocProperties()); 464 SetUseUserData( ((const SfxDocumentInfoItem *)pDocInfoItem)->IsUseUserData() ); 465 466 // add data from dialog for possible recording purposes 467 rReq.AppendItem( SfxDocumentInfoItem( GetTitle(), 468 getDocProperties(), IsUseUserData() ) ); 469 } 470 471 rReq.Done(); 472 } 473 else 474 // nothing done; no recording 475 rReq.Ignore(); 476 477 delete pDlg; 478 } 479 480 return; 481 } 482 483 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 484 485 case SID_EXPORTDOCASPDF: 486 case SID_DIRECTEXPORTDOCASPDF: 487 bIsPDFExport = sal_True; 488 case SID_EXPORTDOC: 489 case SID_SAVEASDOC: 490 case SID_SAVEDOC: 491 { 492 // derived class may decide to abort this 493 if( !QuerySlotExecutable( nId ) ) 494 { 495 rReq.SetReturnValue( SfxBoolItem( 0, sal_False ) ); 496 return; 497 } 498 499 //!! detaillierte Auswertung eines Fehlercodes 500 SfxObjectShellRef xLock( this ); 501 502 // the model can not be closed till the end of this method 503 // if somebody tries to close it during this time the model will be closed 504 // at the end of the method 505 aModelGuard.Init_Impl( uno::Reference< util::XCloseable >( GetModel(), uno::UNO_QUERY ) ); 506 507 sal_Bool bDialogUsed = sal_False; 508 sal_uInt32 nErrorCode = ERRCODE_NONE; 509 510 // by default versions should be preserved always except in case of an explicit 511 // SaveAs via GUI, so the flag must be set accordingly 512 pImp->bPreserveVersions = (nId == SID_SAVEDOC); 513 try 514 { 515 SfxErrorContext aEc( ERRCTX_SFX_SAVEASDOC, GetTitle() ); // ??? 516 517 if ( nId == SID_SAVEASDOC ) 518 { 519 // in case of plugin mode the SaveAs operation means SaveTo 520 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pViewOnlyItem, SfxBoolItem, SID_VIEWONLY, sal_False ); 521 if ( pViewOnlyItem && pViewOnlyItem->GetValue() ) 522 rReq.AppendItem( SfxBoolItem( SID_SAVETO, sal_True ) ); 523 } 524 525 // TODO/LATER: do the following GUI related actions in standalown method 526 // ======================================================================================================== 527 // Introduce a status indicator for GUI operation 528 SFX_REQUEST_ARG( rReq, pStatusIndicatorItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, sal_False ); 529 if ( !pStatusIndicatorItem ) 530 { 531 // get statusindicator 532 uno::Reference< task::XStatusIndicator > xStatusIndicator; 533 SfxViewFrame *pFrame = GetFrame(); 534 if ( pFrame ) 535 { 536 uno::Reference< task::XStatusIndicatorFactory > xStatFactory( 537 pFrame->GetFrame().GetFrameInterface(), 538 uno::UNO_QUERY ); 539 if( xStatFactory.is() ) 540 xStatusIndicator = xStatFactory->createStatusIndicator(); 541 } 542 543 544 OSL_ENSURE( xStatusIndicator.is(), "Can not retrieve default status indicator!\n" ); 545 if ( xStatusIndicator.is() ) 546 { 547 SfxUnoAnyItem aStatIndItem( SID_PROGRESS_STATUSBAR_CONTROL, uno::makeAny( xStatusIndicator ) ); 548 549 if ( nId == SID_SAVEDOC ) 550 { 551 // in case of saving it is not possible to transport the parameters from here 552 // but it is not clear here whether the saving will be done or saveAs operation 553 GetMedium()->GetItemSet()->Put( aStatIndItem ); 554 } 555 556 rReq.AppendItem( aStatIndItem ); 557 } 558 } 559 else if ( nId == SID_SAVEDOC ) 560 { 561 // in case of saving it is not possible to transport the parameters from here 562 // but it is not clear here whether the saving will be done or saveAs operation 563 GetMedium()->GetItemSet()->Put( *pStatusIndicatorItem ); 564 } 565 566 // Introduce an interaction handler for GUI operation 567 SFX_REQUEST_ARG( rReq, pInteractionHandlerItem, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False ); 568 if ( !pInteractionHandlerItem ) 569 { 570 uno::Reference< task::XInteractionHandler > xInteract; 571 uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); 572 if( xServiceManager.is() ) 573 { 574 xInteract = Reference< XInteractionHandler >( 575 xServiceManager->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), 576 UNO_QUERY ); 577 } 578 579 OSL_ENSURE( xInteract.is(), "Can not retrieve default status indicator!\n" ); 580 if ( xInteract.is() ) 581 { 582 SfxUnoAnyItem aInteractionItem( SID_INTERACTIONHANDLER, uno::makeAny( xInteract ) ); 583 if ( nId == SID_SAVEDOC ) 584 { 585 // in case of saving it is not possible to transport the parameters from here 586 // but it is not clear here whether the saving will be done or saveAs operation 587 GetMedium()->GetItemSet()->Put( aInteractionItem ); 588 } 589 590 rReq.AppendItem( aInteractionItem ); 591 } 592 } 593 else if ( nId == SID_SAVEDOC ) 594 { 595 // in case of saving it is not possible to transport the parameters from here 596 // but it is not clear here whether the saving will be done or saveAs operation 597 GetMedium()->GetItemSet()->Put( *pInteractionHandlerItem ); 598 } 599 // ======================================================================================================== 600 601 sal_Bool bPreselectPassword = sal_False; 602 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pOldEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False ); 603 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pOldPasswordItem, SfxStringItem, SID_PASSWORD, sal_False ); 604 if ( pOldEncryptionDataItem || pOldPasswordItem ) 605 bPreselectPassword = sal_True; 606 607 uno::Sequence< beans::PropertyValue > aDispatchArgs; 608 if ( rReq.GetArgs() ) 609 TransformItems( nId, 610 *rReq.GetArgs(), 611 aDispatchArgs, 612 NULL ); 613 614 const SfxSlot* pSlot = GetModule()->GetSlotPool()->GetSlot( nId ); 615 if ( !pSlot ) 616 throw uno::Exception(); 617 618 uno::Reference< lang::XMultiServiceFactory > xEmptyFactory; 619 SfxStoringHelper aHelper( xEmptyFactory ); 620 621 if ( QueryHiddenInformation( bIsPDFExport ? WhenCreatingPDF : WhenSaving, NULL ) == RET_YES ) 622 { 623 bDialogUsed = aHelper.GUIStoreModel( GetModel(), 624 ::rtl::OUString::createFromAscii( pSlot->GetUnoName() ), 625 aDispatchArgs, 626 bPreselectPassword, 627 GetSharedFileURL(), 628 GetDocumentSignatureState() ); 629 } 630 else 631 { 632 // the user has decided not to store the document 633 throw task::ErrorCodeIOException( ::rtl::OUString(), 634 uno::Reference< uno::XInterface >(), 635 ERRCODE_IO_ABORT ); 636 } 637 638 // merge aDispatchArgs to the request 639 SfxAllItemSet aResultParams( GetPool() ); 640 TransformParameters( nId, 641 aDispatchArgs, 642 aResultParams, 643 NULL ); 644 rReq.SetArgs( aResultParams ); 645 646 SFX_REQUEST_ARG( rReq, pFilterNameItem, SfxStringItem, SID_FILTER_NAME, sal_False ); 647 ::rtl::OUString aFilterName = pFilterNameItem ? ::rtl::OUString( pFilterNameItem->GetValue() ) 648 : ::rtl::OUString(); 649 const SfxFilter* pFilt = GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName ); 650 651 OSL_ENSURE( nId == SID_SAVEDOC || pFilt, "The filter can not be zero since it was used for storing!\n" ); 652 if ( bDialogUsed && pFilt 653 && pFilt->IsOwnFormat() 654 && pFilt->UsesStorage() 655 && pFilt->GetVersion() >= SOFFICE_FILEFORMAT_60 ) 656 { 657 SfxViewFrame* pDocViewFrame = SfxViewFrame::GetFirst( this ); 658 if ( pDocViewFrame ) 659 SfxHelp::OpenHelpAgent( &pDocViewFrame->GetFrame(), HID_DID_SAVE_PACKED_XML ); 660 } 661 662 // the StoreAsURL/StoreToURL method have called this method with false 663 // so it has to be restored to true here since it is a call from GUI 664 GetMedium()->SetUpdatePickList( sal_True ); 665 666 // TODO: in future it must be done in followind way 667 // if document is opened from GUI it is immediatelly appeares in the picklist 668 // if the document is a new one then it appeares in the picklist immediatelly 669 // after SaveAs operation triggered from GUI 670 } 671 catch( task::ErrorCodeIOException& aErrorEx ) 672 { 673 nErrorCode = (sal_uInt32)aErrorEx.ErrCode; 674 } 675 catch( Exception& ) 676 { 677 nErrorCode = ERRCODE_IO_GENERAL; 678 } 679 680 // by default versions should be preserved always except in case of an explicit 681 // SaveAs via GUI, so the flag must be reset to guarantee this 682 pImp->bPreserveVersions = sal_True; 683 sal_uIntPtr lErr=GetErrorCode(); 684 685 if ( !lErr && nErrorCode ) 686 lErr = nErrorCode; 687 688 if ( lErr && nErrorCode == ERRCODE_NONE ) 689 { 690 SFX_REQUEST_ARG( rReq, pWarnItem, SfxBoolItem, SID_FAIL_ON_WARNING, sal_False ); 691 if ( pWarnItem && pWarnItem->GetValue() ) 692 nErrorCode = lErr; 693 } 694 695 // may be nErrorCode should be shown in future 696 if ( lErr != ERRCODE_IO_ABORT ) 697 { 698 SfxErrorContext aEc(ERRCTX_SFX_SAVEASDOC,GetTitle()); 699 ErrorHandler::HandleError( lErr ); 700 } 701 702 if ( nId == SID_EXPORTDOCASPDF ) 703 { 704 // This function is used by the SendMail function that needs information if a export 705 // file was written or not. This could be due to cancellation of the export 706 // or due to an error. So IO abort must be handled like an error! 707 nErrorCode = ( lErr != ERRCODE_IO_ABORT ) && ( nErrorCode == ERRCODE_NONE ) ? nErrorCode : lErr; 708 } 709 710 rReq.SetReturnValue( SfxBoolItem(0, nErrorCode == ERRCODE_NONE ) ); 711 712 ResetError(); 713 714 Invalidate(); 715 break; 716 } 717 718 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 719 720 case SID_CLOSEDOC: 721 { 722 SfxViewFrame *pFrame = GetFrame(); 723 if ( pFrame && pFrame->GetFrame().GetParentFrame() ) 724 { 725 // Wenn SID_CLOSEDOC "uber Menue etc. ausgef"uhrt wird, das 726 // aktuelle Dokument aber in einem Frame liegt, soll eigentlich 727 // das FrameSetDocument geclosed werden 728 pFrame->GetTopViewFrame()->GetObjectShell()->ExecuteSlot( rReq ); 729 rReq.Done(); 730 return; 731 } 732 733 sal_Bool bInFrameSet = sal_False; 734 sal_uInt16 nFrames=0; 735 pFrame = SfxViewFrame::GetFirst( this ); 736 while ( pFrame ) 737 { 738 if ( pFrame->GetFrame().GetParentFrame() ) 739 { 740 // Auf dieses Dokument existiert noch eine Sicht, die 741 // in einem FrameSet liegt; diese darf nat"urlich nicht 742 // geclosed werden 743 bInFrameSet = sal_True; 744 } 745 else 746 nFrames++; 747 748 pFrame = SfxViewFrame::GetNext( *pFrame, this ); 749 } 750 751 if ( bInFrameSet ) 752 { 753 // Alle Sichten, die nicht in einem FrameSet liegen, closen 754 pFrame = SfxViewFrame::GetFirst( this ); 755 while ( pFrame ) 756 { 757 if ( !pFrame->GetFrame().GetParentFrame() ) 758 pFrame->GetFrame().DoClose(); 759 pFrame = SfxViewFrame::GetNext( *pFrame, this ); 760 } 761 } 762 763 // Parameter auswerten 764 SFX_REQUEST_ARG(rReq, pSaveItem, SfxBoolItem, SID_CLOSEDOC_SAVE, sal_False); 765 SFX_REQUEST_ARG(rReq, pNameItem, SfxStringItem, SID_CLOSEDOC_FILENAME, sal_False); 766 if ( pSaveItem ) 767 { 768 if ( pSaveItem->GetValue() ) 769 { 770 if ( !pNameItem ) 771 { 772 SbxBase::SetError( SbxERR_WRONG_ARGS ); 773 rReq.Ignore(); 774 return; 775 } 776 SfxAllItemSet aArgs( GetPool() ); 777 SfxStringItem aTmpItem( SID_FILE_NAME, pNameItem->GetValue() ); 778 aArgs.Put( aTmpItem, aTmpItem.Which() ); 779 SfxRequest aSaveAsReq( SID_SAVEASDOC, SFX_CALLMODE_API, aArgs ); 780 ExecFile_Impl( aSaveAsReq ); 781 if ( !aSaveAsReq.IsDone() ) 782 { 783 rReq.Ignore(); 784 return; 785 } 786 } 787 else 788 SetModified(sal_False); 789 } 790 791 // Benutzer bricht ab? 792 if ( !PrepareClose( 2 ) ) 793 { 794 rReq.SetReturnValue( SfxBoolItem(0, sal_False) ); 795 rReq.Done(); 796 return; 797 } 798 799 SetModified( sal_False ); 800 sal_uIntPtr lErr = GetErrorCode(); 801 ErrorHandler::HandleError(lErr); 802 803 rReq.SetReturnValue( SfxBoolItem(0, sal_True) ); 804 rReq.Done(); 805 rReq.ReleaseArgs(); // da der Pool in Close zerst"ort wird 806 DoClose(); 807 return; 808 } 809 810 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 811 case SID_DOCTEMPLATE: 812 { 813 // speichern als Dokumentvorlagen 814 SfxDocumentTemplateDlg *pDlg = 0; 815 SfxErrorContext aEc(ERRCTX_SFX_DOCTEMPLATE,GetTitle()); 816 SfxDocumentTemplates *pTemplates = new SfxDocumentTemplates; 817 818 if ( !rReq.GetArgs() ) 819 { 820 pDlg = new SfxDocumentTemplateDlg(0, pTemplates); 821 if ( RET_OK == pDlg->Execute() && pDlg->GetTemplateName().Len()) 822 { 823 rReq.AppendItem(SfxStringItem( 824 SID_TEMPLATE_NAME, pDlg->GetTemplateName())); 825 rReq.AppendItem(SfxStringItem( 826 SID_TEMPLATE_REGIONNAME, pDlg->GetRegionName())); 827 } 828 else 829 { 830 delete pDlg; 831 rReq.Ignore(); 832 return; 833 } 834 } 835 836 SFX_REQUEST_ARG(rReq, pRegionItem, SfxStringItem, SID_TEMPLATE_REGIONNAME, sal_False); 837 SFX_REQUEST_ARG(rReq, pNameItem, SfxStringItem, SID_TEMPLATE_NAME, sal_False); 838 SFX_REQUEST_ARG(rReq, pRegionNrItem, SfxUInt16Item, SID_TEMPLATE_REGION, sal_False); 839 if ( (!pRegionItem && !pRegionNrItem ) || !pNameItem ) 840 { 841 DBG_ASSERT( rReq.IsAPI(), "non-API call without Arguments" ); 842 SbxBase::SetError( SbxERR_WRONG_ARGS ); 843 rReq.Ignore(); 844 return; 845 } 846 847 ::rtl::OUString aTemplateName = pNameItem->GetValue(); 848 ::rtl::OUString aTemplateGroup; 849 if ( pRegionItem ) 850 aTemplateGroup = pRegionItem->GetValue(); 851 else 852 // pRegionNrItem must not be NULL, it was just checked 853 aTemplateGroup = pTemplates->GetFullRegionName( pRegionNrItem->GetValue() ); 854 // check Group and Name 855 delete pTemplates; 856 857 sal_Bool bOk = sal_False; 858 try 859 { 860 uno::Reference< frame::XStorable > xStorable( GetModel(), uno::UNO_QUERY_THROW ); 861 ::rtl::OUString aService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.DocumentTemplates" ) ); 862 uno::Reference< frame::XDocumentTemplates > xTemplates( 863 comphelper::getProcessServiceFactory()->createInstance( aService ), 864 uno::UNO_QUERY_THROW ); 865 866 bOk = xTemplates->storeTemplate( aTemplateGroup, aTemplateName, xStorable ); 867 } 868 catch( uno::Exception& ) 869 { 870 } 871 872 DELETEX(pDlg); 873 874 rReq.SetReturnValue( SfxBoolItem( 0, bOk ) ); 875 if ( bOk ) 876 { 877 // update the Organizer runtime cache from the template component if the cache has already been created 878 // TODO/LATER: get rid of this cache duplication 879 SfxDocumentTemplates aTemplates; 880 aTemplates.ReInitFromComponent(); 881 } 882 else 883 { 884 ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); 885 return; 886 } 887 888 break; 889 } 890 } 891 892 // Picklisten-Eintrag verhindern 893 if ( rReq.IsAPI() ) 894 GetMedium()->SetUpdatePickList( sal_False ); 895 else if ( rReq.GetArgs() ) 896 { 897 SFX_ITEMSET_GET( *rReq.GetArgs(), pPicklistItem, SfxBoolItem, SID_PICKLIST, sal_False ); 898 if ( pPicklistItem ) 899 GetMedium()->SetUpdatePickList( pPicklistItem->GetValue() ); 900 } 901 902 // Ignore()-Zweige haben schon returnt 903 rReq.Done(); 904 } 905 906 //------------------------------------------------------------------------- 907 908 void SfxObjectShell::GetState_Impl(SfxItemSet &rSet) 909 { 910 DBG_CHKTHIS(SfxObjectShell, 0); 911 SfxWhichIter aIter( rSet ); 912 913 for ( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich() ) 914 { 915 switch ( nWhich ) 916 { 917 case SID_DOCTEMPLATE : 918 { 919 if ( !GetFactory().GetTemplateFilter() ) 920 rSet.DisableItem( nWhich ); 921 break; 922 } 923 924 case SID_VERSION: 925 { 926 SfxObjectShell *pDoc = this; 927 SfxViewFrame* pFrame = GetFrame(); 928 if ( !pFrame ) 929 pFrame = SfxViewFrame::GetFirst( this ); 930 if ( pFrame ) 931 { 932 if ( pFrame->GetFrame().GetParentFrame() ) 933 { 934 pFrame = pFrame->GetTopViewFrame(); 935 pDoc = pFrame->GetObjectShell(); 936 } 937 } 938 939 if ( !pFrame || !pDoc->HasName() || 940 !IsOwnStorageFormat_Impl( *pDoc->GetMedium() ) ) 941 //REMOVE || pDoc->GetMedium()->GetStorage()->GetVersion() < SOFFICE_FILEFORMAT_50 ) 942 rSet.DisableItem( nWhich ); 943 break; 944 } 945 case SID_SAVEDOC: 946 { 947 sal_Bool bMediumRO = IsReadOnlyMedium(); 948 if ( !bMediumRO && GetMedium() && IsModified() ) 949 rSet.Put(SfxStringItem( 950 nWhich, String(SfxResId(STR_SAVEDOC)))); 951 else 952 rSet.DisableItem(nWhich); 953 } 954 break; 955 956 case SID_DOCINFO: 957 if ( 0 != ( pImp->eFlags & SFXOBJECTSHELL_NODOCINFO ) ) 958 rSet.DisableItem( nWhich ); 959 break; 960 961 case SID_CLOSEDOC: 962 { 963 SfxObjectShell *pDoc = this; 964 SfxViewFrame *pFrame = GetFrame(); 965 if ( pFrame && pFrame->GetFrame().GetParentFrame() ) 966 { 967 // Wenn SID_CLOSEDOC "uber Menue etc. ausgef"uhrt wird, das 968 // aktuelle Dokument aber in einem Frame liegt, soll eigentlich 969 // das FrameSetDocument geclosed werden 970 pDoc = pFrame->GetTopViewFrame()->GetObjectShell(); 971 } 972 973 if ( pDoc->GetFlags() & SFXOBJECTSHELL_DONTCLOSE ) 974 rSet.DisableItem(nWhich); 975 else 976 rSet.Put(SfxStringItem(nWhich, String(SfxResId(STR_CLOSEDOC)))); 977 break; 978 } 979 980 case SID_SAVEASDOC: 981 { 982 if( ( pImp->nLoadedFlags & SFX_LOADED_MAINDOCUMENT ) != SFX_LOADED_MAINDOCUMENT ) 983 { 984 rSet.DisableItem( nWhich ); 985 break; 986 } 987 /* 988 const SfxFilter* pCombinedFilters = NULL; 989 SfxFilterContainer* pFilterContainer = GetFactory().GetFilterContainer(); 990 991 if ( pFilterContainer ) 992 { 993 SfxFilterFlags nMust = SFX_FILTER_IMPORT | SFX_FILTER_EXPORT; 994 SfxFilterFlags nDont = SFX_FILTER_NOTINSTALLED | SFX_FILTER_INTERNAL; 995 996 pCombinedFilters = pFilterContainer->GetAnyFilter( nMust, nDont ); 997 } 998 */ 999 if ( /*!pCombinedFilters ||*/ !GetMedium() ) 1000 rSet.DisableItem( nWhich ); 1001 else 1002 rSet.Put( SfxStringItem( nWhich, String( SfxResId( STR_SAVEASDOC ) ) ) ); 1003 break; 1004 } 1005 1006 case SID_EXPORTDOCASPDF: 1007 case SID_DIRECTEXPORTDOCASPDF: 1008 { 1009 /* 1010 1011 search for filter cant work correctly ... 1012 Because it's not clear, which export filter for which office module 1013 must be searched. On the other side it can be very expensive doing so. 1014 The best solution would be: on installation time we should know if pdf feature 1015 was installed or not!!! (e.g. by writing a bool inside cfg) 1016 1017 SfxFilterContainer* pFilterContainer = GetFactory().GetFilterContainer(); 1018 if ( pFilterContainer ) 1019 { 1020 String aPDFExtension = String::CreateFromAscii( "pdf" ); 1021 const SfxFilter* pFilter = pFilterContainer->GetFilter4Extension( aPDFExtension, SFX_FILTER_EXPORT ); 1022 if ( pFilter != NULL ) 1023 break; 1024 } 1025 1026 rSet.DisableItem( nWhich ); 1027 */ 1028 break; 1029 } 1030 1031 case SID_DOC_MODIFIED: 1032 { 1033 rSet.Put( SfxStringItem( SID_DOC_MODIFIED, IsModified() ? '*' : ' ' ) ); 1034 break; 1035 } 1036 1037 case SID_MODIFIED: 1038 { 1039 rSet.Put( SfxBoolItem( SID_MODIFIED, IsModified() ) ); 1040 break; 1041 } 1042 1043 case SID_DOCINFO_TITLE: 1044 { 1045 rSet.Put( SfxStringItem( 1046 SID_DOCINFO_TITLE, getDocProperties()->getTitle() ) ); 1047 break; 1048 } 1049 case SID_FILE_NAME: 1050 { 1051 if( GetMedium() && HasName() ) 1052 rSet.Put( SfxStringItem( 1053 SID_FILE_NAME, GetMedium()->GetName() ) ); 1054 break; 1055 } 1056 case SID_SIGNATURE: 1057 { 1058 rSet.Put( SfxUInt16Item( SID_SIGNATURE, GetDocumentSignatureState() ) ); 1059 break; 1060 } 1061 case SID_MACRO_SIGNATURE: 1062 { 1063 // the slot makes sense only if there is a macro in the document 1064 if ( pImp->documentStorageHasMacros() || pImp->aMacroMode.hasMacroLibrary() ) 1065 rSet.Put( SfxUInt16Item( SID_MACRO_SIGNATURE, GetScriptingSignatureState() ) ); 1066 else 1067 rSet.DisableItem( nWhich ); 1068 break; 1069 } 1070 } 1071 } 1072 } 1073 1074 //-------------------------------------------------------------------- 1075 1076 void SfxObjectShell::ExecProps_Impl(SfxRequest &rReq) 1077 { 1078 switch ( rReq.GetSlot() ) 1079 { 1080 case SID_MODIFIED: 1081 { 1082 SetModified( ( (SfxBoolItem&) rReq.GetArgs()->Get(SID_MODIFIED)).GetValue() ); 1083 rReq.Done(); 1084 break; 1085 } 1086 1087 case SID_DOCTITLE: 1088 SetTitle( ( (SfxStringItem&) rReq.GetArgs()->Get(SID_DOCTITLE)).GetValue() ); 1089 rReq.Done(); 1090 break; 1091 1092 case SID_DOCINFO_AUTHOR : 1093 { 1094 ::rtl::OUString aStr = ( (SfxStringItem&)rReq.GetArgs()->Get(rReq.GetSlot())).GetValue(); 1095 getDocProperties()->setAuthor( aStr ); 1096 break; 1097 } 1098 1099 case SID_DOCINFO_COMMENTS : 1100 { 1101 ::rtl::OUString aStr = ( (SfxStringItem&)rReq.GetArgs()->Get(rReq.GetSlot())).GetValue(); 1102 getDocProperties()->setDescription( aStr ); 1103 break; 1104 } 1105 1106 case SID_DOCINFO_KEYWORDS : 1107 { 1108 ::rtl::OUString aStr = ( (SfxStringItem&)rReq.GetArgs()->Get(rReq.GetSlot())).GetValue(); 1109 getDocProperties()->setKeywords( 1110 ::comphelper::string::convertCommaSeparated(aStr) ); 1111 break; 1112 } 1113 } 1114 } 1115 1116 //-------------------------------------------------------------------- 1117 1118 void SfxObjectShell::StateProps_Impl(SfxItemSet &rSet) 1119 { 1120 SfxWhichIter aIter(rSet); 1121 for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() ) 1122 { 1123 switch ( nSID ) 1124 { 1125 case SID_DOCINFO_AUTHOR : 1126 { 1127 rSet.Put( SfxStringItem( nSID, 1128 getDocProperties()->getAuthor() ) ); 1129 break; 1130 } 1131 1132 case SID_DOCINFO_COMMENTS : 1133 { 1134 rSet.Put( SfxStringItem( nSID, 1135 getDocProperties()->getDescription()) ); 1136 break; 1137 } 1138 1139 case SID_DOCINFO_KEYWORDS : 1140 { 1141 rSet.Put( SfxStringItem( nSID, ::comphelper::string:: 1142 convertCommaSeparated(getDocProperties()->getKeywords())) ); 1143 break; 1144 } 1145 1146 case SID_DOCPATH: 1147 { 1148 DBG_ERROR( "Not supported anymore!" ); 1149 break; 1150 } 1151 1152 case SID_DOCFULLNAME: 1153 { 1154 rSet.Put( SfxStringItem( SID_DOCFULLNAME, GetTitle(SFX_TITLE_FULLNAME) ) ); 1155 break; 1156 } 1157 1158 case SID_DOCTITLE: 1159 { 1160 rSet.Put( SfxStringItem( SID_DOCTITLE, GetTitle() ) ); 1161 break; 1162 } 1163 1164 case SID_DOC_READONLY: 1165 { 1166 rSet.Put( SfxBoolItem( SID_DOC_READONLY, IsReadOnly() ) ); 1167 break; 1168 } 1169 1170 case SID_DOC_SAVED: 1171 { 1172 rSet.Put( SfxBoolItem( SID_DOC_SAVED, !IsModified() ) ); 1173 break; 1174 } 1175 1176 case SID_CLOSING: 1177 { 1178 rSet.Put( SfxBoolItem( SID_CLOSING, false ) ); 1179 break; 1180 } 1181 1182 case SID_DOC_LOADING: 1183 rSet.Put( SfxBoolItem( nSID, SFX_LOADED_MAINDOCUMENT != 1184 ( pImp->nLoadedFlags & SFX_LOADED_MAINDOCUMENT ) ) ); 1185 break; 1186 1187 case SID_IMG_LOADING: 1188 rSet.Put( SfxBoolItem( nSID, SFX_LOADED_IMAGES != 1189 ( pImp->nLoadedFlags & SFX_LOADED_IMAGES ) ) ); 1190 break; 1191 } 1192 } 1193 } 1194 1195 //-------------------------------------------------------------------- 1196 1197 void SfxObjectShell::ExecView_Impl(SfxRequest &rReq) 1198 { 1199 switch ( rReq.GetSlot() ) 1200 { 1201 case SID_ACTIVATE: 1202 { 1203 SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this, sal_True ); 1204 if ( pFrame ) 1205 pFrame->GetFrame().Appear(); 1206 rReq.SetReturnValue( SfxObjectItem( 0, pFrame ) ); 1207 rReq.Done(); 1208 break; 1209 } 1210 case SID_NEWWINDOWFOREDIT: 1211 { 1212 SfxViewFrame* pFrame = SfxViewFrame::Current(); 1213 if( pFrame->GetObjectShell() == this && 1214 ( pFrame->GetFrameType() & SFXFRAME_HASTITLE ) ) 1215 pFrame->ExecuteSlot( rReq ); 1216 else 1217 { 1218 String aFileName( GetObjectShell()->GetMedium()->GetName() ); 1219 if ( aFileName.Len() ) 1220 { 1221 SfxStringItem aName( SID_FILE_NAME, aFileName ); 1222 SfxBoolItem aCreateView( SID_OPEN_NEW_VIEW, sal_True ); 1223 SFX_APP()->GetAppDispatcher_Impl()->Execute( 1224 SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, &aName, 1225 &aCreateView, 0L); 1226 } 1227 } 1228 } 1229 } 1230 } 1231 1232 //-------------------------------------------------------------------- 1233 1234 void SfxObjectShell::StateView_Impl(SfxItemSet& /*rSet*/) 1235 { 1236 } 1237 1238 sal_uInt16 SfxObjectShell::ImplCheckSignaturesInformation( const uno::Sequence< security::DocumentSignatureInformation >& aInfos ) 1239 { 1240 sal_Bool bCertValid = sal_True; 1241 sal_uInt16 nResult = SIGNATURESTATE_NOSIGNATURES; 1242 int nInfos = aInfos.getLength(); 1243 bool bCompleteSignature = true; 1244 if( nInfos ) 1245 { 1246 nResult = SIGNATURESTATE_SIGNATURES_OK; 1247 for ( int n = 0; n < nInfos; n++ ) 1248 { 1249 if ( bCertValid ) 1250 { 1251 sal_Int32 nCertStat = aInfos[n].CertificateStatus; 1252 bCertValid = nCertStat == security::CertificateValidity::VALID ? sal_True : sal_False; 1253 } 1254 1255 if ( !aInfos[n].SignatureIsValid ) 1256 { 1257 nResult = SIGNATURESTATE_SIGNATURES_BROKEN; 1258 break; // we know enough 1259 } 1260 bCompleteSignature &= !aInfos[n].PartialDocumentSignature; 1261 } 1262 } 1263 1264 if ( nResult == SIGNATURESTATE_SIGNATURES_OK && !bCertValid ) 1265 nResult = SIGNATURESTATE_SIGNATURES_NOTVALIDATED; 1266 else if ( nResult == SIGNATURESTATE_SIGNATURES_OK && bCertValid && !bCompleteSignature) 1267 nResult = SIGNATURESTATE_SIGNATURES_PARTIAL_OK; 1268 1269 // this code must not check whether the document is modified 1270 // it should only check the provided info 1271 1272 return nResult; 1273 } 1274 1275 uno::Sequence< security::DocumentSignatureInformation > SfxObjectShell::ImplAnalyzeSignature( sal_Bool bScriptingContent, const uno::Reference< security::XDocumentDigitalSignatures >& xSigner ) 1276 { 1277 uno::Sequence< security::DocumentSignatureInformation > aResult; 1278 uno::Reference< security::XDocumentDigitalSignatures > xLocSigner = xSigner; 1279 1280 if ( GetMedium() && GetMedium()->GetName().Len() && IsOwnStorageFormat_Impl( *GetMedium()) && GetMedium()->GetStorage().is() ) 1281 { 1282 try 1283 { 1284 if ( !xLocSigner.is() ) 1285 { 1286 uno::Sequence< uno::Any > aArgs( 1 ); 1287 aArgs[0] <<= ::rtl::OUString(); 1288 try 1289 { 1290 uno::Reference < beans::XPropertySet > xPropSet( GetStorage(), uno::UNO_QUERY_THROW ); 1291 aArgs[0] = xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ); 1292 } 1293 catch( uno::Exception& ) 1294 { 1295 } 1296 1297 xLocSigner.set( comphelper::getProcessServiceFactory()->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ), aArgs ), uno::UNO_QUERY_THROW ); 1298 1299 } 1300 1301 if ( bScriptingContent ) 1302 aResult = xLocSigner->verifyScriptingContentSignatures( GetMedium()->GetZipStorageToSign_Impl(), 1303 uno::Reference< io::XInputStream >() ); 1304 else 1305 aResult = xLocSigner->verifyDocumentContentSignatures( GetMedium()->GetZipStorageToSign_Impl(), 1306 uno::Reference< io::XInputStream >() ); 1307 } 1308 catch( com::sun::star::uno::Exception& ) 1309 { 1310 } 1311 } 1312 1313 return aResult; 1314 } 1315 1316 sal_uInt16 SfxObjectShell::ImplGetSignatureState( sal_Bool bScriptingContent ) 1317 { 1318 sal_Int16* pState = bScriptingContent ? &pImp->nScriptingSignatureState : &pImp->nDocumentSignatureState; 1319 1320 if ( *pState == SIGNATURESTATE_UNKNOWN ) 1321 { 1322 *pState = SIGNATURESTATE_NOSIGNATURES; 1323 1324 uno::Sequence< security::DocumentSignatureInformation > aInfos = ImplAnalyzeSignature( bScriptingContent ); 1325 *pState = ImplCheckSignaturesInformation( aInfos ); 1326 } 1327 1328 if ( *pState == SIGNATURESTATE_SIGNATURES_OK || *pState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED 1329 || *pState == SIGNATURESTATE_SIGNATURES_PARTIAL_OK) 1330 { 1331 if ( IsModified() ) 1332 *pState = SIGNATURESTATE_SIGNATURES_INVALID; 1333 } 1334 1335 return (sal_uInt16)*pState; 1336 } 1337 1338 void SfxObjectShell::ImplSign( sal_Bool bScriptingContent ) 1339 { 1340 // Check if it is stored in OASIS format... 1341 if ( GetMedium() 1342 && GetMedium()->GetFilter() 1343 && GetMedium()->GetName().Len() 1344 && ( !GetMedium()->GetFilter()->IsOwnFormat() 1345 || !GetMedium()->HasStorage_Impl() 1346 ) 1347 ) 1348 { 1349 // Only OASIS and OOo6.x formats will be handled further 1350 InfoBox( NULL, SfxResId( RID_XMLSEC_INFO_WRONGDOCFORMAT ) ).Execute(); 1351 return; 1352 } 1353 1354 // check whether the document is signed 1355 ImplGetSignatureState( sal_False ); // document signature 1356 ImplGetSignatureState( sal_True ); // script signature 1357 sal_Bool bHasSign = ( pImp->nScriptingSignatureState != SIGNATURESTATE_NOSIGNATURES || pImp->nDocumentSignatureState != SIGNATURESTATE_NOSIGNATURES ); 1358 1359 // the target ODF version on saving 1360 SvtSaveOptions aSaveOpt; 1361 SvtSaveOptions::ODFDefaultVersion nVersion = aSaveOpt.GetODFDefaultVersion(); 1362 1363 // the document is not new and is not modified 1364 ::rtl::OUString aODFVersion; 1365 try 1366 { 1367 // check the version of the document 1368 uno::Reference < beans::XPropertySet > xPropSet( GetStorage(), uno::UNO_QUERY_THROW ); 1369 xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ) >>= aODFVersion; 1370 } 1371 catch( uno::Exception& ) 1372 {} 1373 1374 bool bNoSig = false; 1375 1376 if ( IsModified() || !GetMedium() || !GetMedium()->GetName().Len() 1377 || (!aODFVersion.equals( ODFVER_012_TEXT ) && !bHasSign) ) 1378 { 1379 // the document might need saving ( new, modified or in ODF1.1 format without signature ) 1380 1381 if ( nVersion >= SvtSaveOptions::ODFVER_012 ) 1382 { 1383 1384 if ( (bHasSign && QueryBox( NULL, SfxResId( MSG_XMLSEC_QUERY_SAVESIGNEDBEFORESIGN ) ).Execute() == RET_YES) 1385 || (!bHasSign && QueryBox( NULL, SfxResId( RID_XMLSEC_QUERY_SAVEBEFORESIGN ) ).Execute() == RET_YES) ) 1386 { 1387 sal_uInt16 nId = SID_SAVEDOC; 1388 if ( !GetMedium() || !GetMedium()->GetName().Len() ) 1389 nId = SID_SAVEASDOC; 1390 SfxRequest aSaveRequest( nId, 0, GetPool() ); 1391 //ToDo: Review. We needed to call SetModified, otherwise the document would not be saved. 1392 SetModified(sal_True); 1393 ExecFile_Impl( aSaveRequest ); 1394 1395 // Check if it is stored in OASIS format... 1396 if ( GetMedium() && GetMedium()->GetFilter() 1397 && ( !GetMedium()->GetFilter()->IsOwnFormat() || !GetMedium()->HasStorage_Impl() 1398 || SotStorage::GetVersion( GetMedium()->GetStorage() ) <= SOFFICE_FILEFORMAT_60 ) ) 1399 { 1400 // Only OASIS format will be handled further 1401 InfoBox( NULL, SfxResId( RID_XMLSEC_INFO_WRONGDOCFORMAT ) ).Execute(); 1402 return; 1403 } 1404 } 1405 else 1406 { 1407 //When the document is modified then we must not show the digital signatures dialog 1408 //If we have come here then the user denied to save. 1409 if (!bHasSign) 1410 bNoSig = true; 1411 } 1412 } 1413 else 1414 { 1415 ErrorBox( NULL, WB_OK, SfxResId( STR_XMLSEC_ODF12_EXPECTED ) ).Execute(); 1416 return; 1417 } 1418 1419 if ( IsModified() || !GetMedium() || !GetMedium()->GetName().Len() ) 1420 return; 1421 } 1422 1423 // the document is not modified currently, so it can not become modified after signing 1424 sal_Bool bAllowModifiedBack = sal_False; 1425 if ( IsEnableSetModified() ) 1426 { 1427 EnableSetModified( sal_False ); 1428 bAllowModifiedBack = sal_True; 1429 } 1430 1431 // we have to store to the original document, the original medium should be closed for this time 1432 if ( !bNoSig 1433 && ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) ) 1434 { 1435 GetMedium()->CloseAndRelease(); 1436 1437 // We sign only ODF1.2, that means that if this point has been reached, 1438 // the ODF1.2 signing process should be used. 1439 // This code still might be called to show the signature of ODF1.1 document. 1440 sal_Bool bSigned = GetMedium()->SignContents_Impl( 1441 bScriptingContent, 1442 aODFVersion, 1443 pImp->nDocumentSignatureState == SIGNATURESTATE_SIGNATURES_OK 1444 || pImp->nDocumentSignatureState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED 1445 || pImp->nDocumentSignatureState == SIGNATURESTATE_SIGNATURES_PARTIAL_OK); 1446 1447 DoSaveCompleted( GetMedium() ); 1448 1449 if ( bSigned ) 1450 { 1451 if ( bScriptingContent ) 1452 { 1453 pImp->nScriptingSignatureState = SIGNATURESTATE_UNKNOWN;// Re-Check 1454 1455 // adding of scripting signature removes existing document signature 1456 pImp->nDocumentSignatureState = SIGNATURESTATE_UNKNOWN;// Re-Check 1457 } 1458 else 1459 pImp->nDocumentSignatureState = SIGNATURESTATE_UNKNOWN;// Re-Check 1460 1461 pImp->bSignatureErrorIsShown = sal_False; 1462 1463 Invalidate( SID_SIGNATURE ); 1464 Invalidate( SID_MACRO_SIGNATURE ); 1465 Broadcast( SfxSimpleHint(SFX_HINT_TITLECHANGED) ); 1466 } 1467 } 1468 1469 if ( bAllowModifiedBack ) 1470 EnableSetModified( sal_True ); 1471 } 1472 1473 sal_uInt16 SfxObjectShell::GetDocumentSignatureState() 1474 { 1475 return ImplGetSignatureState( sal_False ); 1476 } 1477 1478 void SfxObjectShell::SignDocumentContent() 1479 { 1480 ImplSign( sal_False ); 1481 } 1482 1483 sal_uInt16 SfxObjectShell::GetScriptingSignatureState() 1484 { 1485 return ImplGetSignatureState( sal_True ); 1486 } 1487 1488 void SfxObjectShell::SignScriptingContent() 1489 { 1490 ImplSign( sal_True ); 1491 } 1492 1493 // static 1494 const uno::Sequence<sal_Int8>& SfxObjectShell::getUnoTunnelId() 1495 { 1496 static uno::Sequence<sal_Int8> * pSeq = 0; 1497 if( !pSeq ) 1498 { 1499 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 1500 if( !pSeq ) 1501 { 1502 static uno::Sequence< sal_Int8 > aSeq( 16 ); 1503 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); 1504 pSeq = &aSeq; 1505 } 1506 } 1507 return *pSeq; 1508 } 1509