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 uno::Reference < frame::XController > xCtrl( GetModel()->getCurrentController() ); 534 if ( xCtrl.is() ) 535 { 536 uno::Reference< task::XStatusIndicatorFactory > xStatFactory( xCtrl->getFrame(), uno::UNO_QUERY ); 537 if( xStatFactory.is() ) 538 xStatusIndicator = xStatFactory->createStatusIndicator(); 539 } 540 541 OSL_ENSURE( xStatusIndicator.is(), "Can not retrieve default status indicator!\n" ); 542 543 if ( xStatusIndicator.is() ) 544 { 545 SfxUnoAnyItem aStatIndItem( SID_PROGRESS_STATUSBAR_CONTROL, uno::makeAny( xStatusIndicator ) ); 546 547 if ( nId == SID_SAVEDOC ) 548 { 549 // in case of saving it is not possible to transport the parameters from here 550 // but it is not clear here whether the saving will be done or saveAs operation 551 GetMedium()->GetItemSet()->Put( aStatIndItem ); 552 } 553 554 rReq.AppendItem( aStatIndItem ); 555 } 556 } 557 else if ( nId == SID_SAVEDOC ) 558 { 559 // in case of saving it is not possible to transport the parameters from here 560 // but it is not clear here whether the saving will be done or saveAs operation 561 GetMedium()->GetItemSet()->Put( *pStatusIndicatorItem ); 562 } 563 564 // Introduce an interaction handler for GUI operation 565 SFX_REQUEST_ARG( rReq, pInteractionHandlerItem, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False ); 566 if ( !pInteractionHandlerItem ) 567 { 568 uno::Reference< task::XInteractionHandler > xInteract; 569 uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); 570 if( xServiceManager.is() ) 571 { 572 xInteract = Reference< XInteractionHandler >( 573 xServiceManager->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), 574 UNO_QUERY ); 575 } 576 577 OSL_ENSURE( xInteract.is(), "Can not retrieve default status indicator!\n" ); 578 if ( xInteract.is() ) 579 { 580 SfxUnoAnyItem aInteractionItem( SID_INTERACTIONHANDLER, uno::makeAny( xInteract ) ); 581 if ( nId == SID_SAVEDOC ) 582 { 583 // in case of saving it is not possible to transport the parameters from here 584 // but it is not clear here whether the saving will be done or saveAs operation 585 GetMedium()->GetItemSet()->Put( aInteractionItem ); 586 } 587 588 rReq.AppendItem( aInteractionItem ); 589 } 590 } 591 else if ( nId == SID_SAVEDOC ) 592 { 593 // in case of saving it is not possible to transport the parameters from here 594 // but it is not clear here whether the saving will be done or saveAs operation 595 GetMedium()->GetItemSet()->Put( *pInteractionHandlerItem ); 596 } 597 // ======================================================================================================== 598 599 sal_Bool bPreselectPassword = sal_False; 600 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pOldEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False ); 601 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pOldPasswordItem, SfxStringItem, SID_PASSWORD, sal_False ); 602 if ( pOldEncryptionDataItem || pOldPasswordItem ) 603 bPreselectPassword = sal_True; 604 605 uno::Sequence< beans::PropertyValue > aDispatchArgs; 606 if ( rReq.GetArgs() ) 607 TransformItems( nId, 608 *rReq.GetArgs(), 609 aDispatchArgs, 610 NULL ); 611 612 const SfxSlot* pSlot = GetModule()->GetSlotPool()->GetSlot( nId ); 613 if ( !pSlot ) 614 throw uno::Exception(); 615 616 uno::Reference< lang::XMultiServiceFactory > xEmptyFactory; 617 SfxStoringHelper aHelper( xEmptyFactory ); 618 619 if ( QueryHiddenInformation( bIsPDFExport ? WhenCreatingPDF : WhenSaving, NULL ) == RET_YES ) 620 { 621 bDialogUsed = aHelper.GUIStoreModel( GetModel(), 622 ::rtl::OUString::createFromAscii( pSlot->GetUnoName() ), 623 aDispatchArgs, 624 bPreselectPassword, 625 GetSharedFileURL(), 626 GetDocumentSignatureState() ); 627 } 628 else 629 { 630 // the user has decided not to store the document 631 throw task::ErrorCodeIOException( ::rtl::OUString(), 632 uno::Reference< uno::XInterface >(), 633 ERRCODE_IO_ABORT ); 634 } 635 636 // merge aDispatchArgs to the request 637 SfxAllItemSet aResultParams( GetPool() ); 638 TransformParameters( nId, 639 aDispatchArgs, 640 aResultParams, 641 NULL ); 642 rReq.SetArgs( aResultParams ); 643 644 SFX_REQUEST_ARG( rReq, pFilterNameItem, SfxStringItem, SID_FILTER_NAME, sal_False ); 645 ::rtl::OUString aFilterName = pFilterNameItem ? ::rtl::OUString( pFilterNameItem->GetValue() ) 646 : ::rtl::OUString(); 647 const SfxFilter* pFilt = GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName ); 648 649 OSL_ENSURE( nId == SID_SAVEDOC || pFilt, "The filter can not be zero since it was used for storing!\n" ); 650 if ( bDialogUsed && pFilt 651 && pFilt->IsOwnFormat() 652 && pFilt->UsesStorage() 653 && pFilt->GetVersion() >= SOFFICE_FILEFORMAT_60 ) 654 { 655 SfxViewFrame* pDocViewFrame = SfxViewFrame::GetFirst( this ); 656 if ( pDocViewFrame ) 657 SfxHelp::OpenHelpAgent( &pDocViewFrame->GetFrame(), HID_DID_SAVE_PACKED_XML ); 658 } 659 660 // the StoreAsURL/StoreToURL method have called this method with false 661 // so it has to be restored to true here since it is a call from GUI 662 GetMedium()->SetUpdatePickList( sal_True ); 663 664 // TODO: in future it must be done in followind way 665 // if document is opened from GUI it is immediatelly appeares in the picklist 666 // if the document is a new one then it appeares in the picklist immediatelly 667 // after SaveAs operation triggered from GUI 668 } 669 catch( task::ErrorCodeIOException& aErrorEx ) 670 { 671 nErrorCode = (sal_uInt32)aErrorEx.ErrCode; 672 } 673 catch( Exception& ) 674 { 675 nErrorCode = ERRCODE_IO_GENERAL; 676 } 677 678 // by default versions should be preserved always except in case of an explicit 679 // SaveAs via GUI, so the flag must be reset to guarantee this 680 pImp->bPreserveVersions = sal_True; 681 sal_uIntPtr lErr=GetErrorCode(); 682 683 if ( !lErr && nErrorCode ) 684 lErr = nErrorCode; 685 686 if ( lErr && nErrorCode == ERRCODE_NONE ) 687 { 688 SFX_REQUEST_ARG( rReq, pWarnItem, SfxBoolItem, SID_FAIL_ON_WARNING, sal_False ); 689 if ( pWarnItem && pWarnItem->GetValue() ) 690 nErrorCode = lErr; 691 } 692 693 // may be nErrorCode should be shown in future 694 if ( lErr != ERRCODE_IO_ABORT ) 695 { 696 SfxErrorContext aEc(ERRCTX_SFX_SAVEASDOC,GetTitle()); 697 ErrorHandler::HandleError( lErr ); 698 } 699 700 if ( nId == SID_EXPORTDOCASPDF ) 701 { 702 // This function is used by the SendMail function that needs information if a export 703 // file was written or not. This could be due to cancellation of the export 704 // or due to an error. So IO abort must be handled like an error! 705 nErrorCode = ( lErr != ERRCODE_IO_ABORT ) && ( nErrorCode == ERRCODE_NONE ) ? nErrorCode : lErr; 706 } 707 708 rReq.SetReturnValue( SfxBoolItem(0, nErrorCode == ERRCODE_NONE ) ); 709 710 ResetError(); 711 712 Invalidate(); 713 break; 714 } 715 716 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 717 718 case SID_CLOSEDOC: 719 { 720 SfxViewFrame *pFrame = GetFrame(); 721 if ( pFrame && pFrame->GetFrame().GetParentFrame() ) 722 { 723 // Wenn SID_CLOSEDOC "uber Menue etc. ausgef"uhrt wird, das 724 // aktuelle Dokument aber in einem Frame liegt, soll eigentlich 725 // das FrameSetDocument geclosed werden 726 pFrame->GetTopViewFrame()->GetObjectShell()->ExecuteSlot( rReq ); 727 rReq.Done(); 728 return; 729 } 730 731 sal_Bool bInFrameSet = sal_False; 732 sal_uInt16 nFrames=0; 733 pFrame = SfxViewFrame::GetFirst( this ); 734 while ( pFrame ) 735 { 736 if ( pFrame->GetFrame().GetParentFrame() ) 737 { 738 // Auf dieses Dokument existiert noch eine Sicht, die 739 // in einem FrameSet liegt; diese darf nat"urlich nicht 740 // geclosed werden 741 bInFrameSet = sal_True; 742 } 743 else 744 nFrames++; 745 746 pFrame = SfxViewFrame::GetNext( *pFrame, this ); 747 } 748 749 if ( bInFrameSet ) 750 { 751 // Alle Sichten, die nicht in einem FrameSet liegen, closen 752 pFrame = SfxViewFrame::GetFirst( this ); 753 while ( pFrame ) 754 { 755 if ( !pFrame->GetFrame().GetParentFrame() ) 756 pFrame->GetFrame().DoClose(); 757 pFrame = SfxViewFrame::GetNext( *pFrame, this ); 758 } 759 } 760 761 // Parameter auswerten 762 SFX_REQUEST_ARG(rReq, pSaveItem, SfxBoolItem, SID_CLOSEDOC_SAVE, sal_False); 763 SFX_REQUEST_ARG(rReq, pNameItem, SfxStringItem, SID_CLOSEDOC_FILENAME, sal_False); 764 if ( pSaveItem ) 765 { 766 if ( pSaveItem->GetValue() ) 767 { 768 if ( !pNameItem ) 769 { 770 SbxBase::SetError( SbxERR_WRONG_ARGS ); 771 rReq.Ignore(); 772 return; 773 } 774 SfxAllItemSet aArgs( GetPool() ); 775 SfxStringItem aTmpItem( SID_FILE_NAME, pNameItem->GetValue() ); 776 aArgs.Put( aTmpItem, aTmpItem.Which() ); 777 SfxRequest aSaveAsReq( SID_SAVEASDOC, SFX_CALLMODE_API, aArgs ); 778 ExecFile_Impl( aSaveAsReq ); 779 if ( !aSaveAsReq.IsDone() ) 780 { 781 rReq.Ignore(); 782 return; 783 } 784 } 785 else 786 SetModified(sal_False); 787 } 788 789 // Benutzer bricht ab? 790 if ( !PrepareClose( 2 ) ) 791 { 792 rReq.SetReturnValue( SfxBoolItem(0, sal_False) ); 793 rReq.Done(); 794 return; 795 } 796 797 SetModified( sal_False ); 798 sal_uIntPtr lErr = GetErrorCode(); 799 ErrorHandler::HandleError(lErr); 800 801 rReq.SetReturnValue( SfxBoolItem(0, sal_True) ); 802 rReq.Done(); 803 rReq.ReleaseArgs(); // da der Pool in Close zerst"ort wird 804 DoClose(); 805 return; 806 } 807 808 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 809 case SID_DOCTEMPLATE: 810 { 811 // speichern als Dokumentvorlagen 812 SfxDocumentTemplateDlg *pDlg = 0; 813 SfxErrorContext aEc(ERRCTX_SFX_DOCTEMPLATE,GetTitle()); 814 SfxDocumentTemplates *pTemplates = new SfxDocumentTemplates; 815 816 if ( !rReq.GetArgs() ) 817 { 818 pDlg = new SfxDocumentTemplateDlg(0, pTemplates); 819 if ( RET_OK == pDlg->Execute() && pDlg->GetTemplateName().Len()) 820 { 821 rReq.AppendItem(SfxStringItem( 822 SID_TEMPLATE_NAME, pDlg->GetTemplateName())); 823 rReq.AppendItem(SfxStringItem( 824 SID_TEMPLATE_REGIONNAME, pDlg->GetRegionName())); 825 } 826 else 827 { 828 delete pDlg; 829 rReq.Ignore(); 830 return; 831 } 832 } 833 834 SFX_REQUEST_ARG(rReq, pRegionItem, SfxStringItem, SID_TEMPLATE_REGIONNAME, sal_False); 835 SFX_REQUEST_ARG(rReq, pNameItem, SfxStringItem, SID_TEMPLATE_NAME, sal_False); 836 SFX_REQUEST_ARG(rReq, pRegionNrItem, SfxUInt16Item, SID_TEMPLATE_REGION, sal_False); 837 if ( (!pRegionItem && !pRegionNrItem ) || !pNameItem ) 838 { 839 DBG_ASSERT( rReq.IsAPI(), "non-API call without Arguments" ); 840 SbxBase::SetError( SbxERR_WRONG_ARGS ); 841 rReq.Ignore(); 842 return; 843 } 844 845 ::rtl::OUString aTemplateName = pNameItem->GetValue(); 846 ::rtl::OUString aTemplateGroup; 847 if ( pRegionItem ) 848 aTemplateGroup = pRegionItem->GetValue(); 849 else 850 // pRegionNrItem must not be NULL, it was just checked 851 aTemplateGroup = pTemplates->GetFullRegionName( pRegionNrItem->GetValue() ); 852 // check Group and Name 853 delete pTemplates; 854 855 sal_Bool bOk = sal_False; 856 try 857 { 858 uno::Reference< frame::XStorable > xStorable( GetModel(), uno::UNO_QUERY_THROW ); 859 ::rtl::OUString aService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.DocumentTemplates" ) ); 860 uno::Reference< frame::XDocumentTemplates > xTemplates( 861 comphelper::getProcessServiceFactory()->createInstance( aService ), 862 uno::UNO_QUERY_THROW ); 863 864 bOk = xTemplates->storeTemplate( aTemplateGroup, aTemplateName, xStorable ); 865 } 866 catch( uno::Exception& ) 867 { 868 } 869 870 DELETEX(pDlg); 871 872 rReq.SetReturnValue( SfxBoolItem( 0, bOk ) ); 873 if ( bOk ) 874 { 875 // update the Organizer runtime cache from the template component if the cache has already been created 876 // TODO/LATER: get rid of this cache duplication 877 SfxDocumentTemplates aTemplates; 878 aTemplates.ReInitFromComponent(); 879 } 880 else 881 { 882 ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); 883 return; 884 } 885 886 break; 887 } 888 } 889 890 // Picklisten-Eintrag verhindern 891 if ( rReq.IsAPI() ) 892 GetMedium()->SetUpdatePickList( sal_False ); 893 else if ( rReq.GetArgs() ) 894 { 895 SFX_ITEMSET_GET( *rReq.GetArgs(), pPicklistItem, SfxBoolItem, SID_PICKLIST, sal_False ); 896 if ( pPicklistItem ) 897 GetMedium()->SetUpdatePickList( pPicklistItem->GetValue() ); 898 } 899 900 // Ignore()-Zweige haben schon returnt 901 rReq.Done(); 902 } 903 904 //------------------------------------------------------------------------- 905 906 void SfxObjectShell::GetState_Impl(SfxItemSet &rSet) 907 { 908 DBG_CHKTHIS(SfxObjectShell, 0); 909 SfxWhichIter aIter( rSet ); 910 911 for ( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich() ) 912 { 913 switch ( nWhich ) 914 { 915 case SID_DOCTEMPLATE : 916 { 917 if ( !GetFactory().GetTemplateFilter() ) 918 rSet.DisableItem( nWhich ); 919 break; 920 } 921 922 case SID_VERSION: 923 { 924 SfxObjectShell *pDoc = this; 925 SfxViewFrame* pFrame = GetFrame(); 926 if ( !pFrame ) 927 pFrame = SfxViewFrame::GetFirst( this ); 928 if ( pFrame ) 929 { 930 if ( pFrame->GetFrame().GetParentFrame() ) 931 { 932 pFrame = pFrame->GetTopViewFrame(); 933 pDoc = pFrame->GetObjectShell(); 934 } 935 } 936 937 if ( !pFrame || !pDoc->HasName() || 938 !IsOwnStorageFormat_Impl( *pDoc->GetMedium() ) ) 939 //REMOVE || pDoc->GetMedium()->GetStorage()->GetVersion() < SOFFICE_FILEFORMAT_50 ) 940 rSet.DisableItem( nWhich ); 941 break; 942 } 943 case SID_SAVEDOC: 944 { 945 sal_Bool bMediumRO = IsReadOnlyMedium(); 946 if ( !bMediumRO && GetMedium() && IsModified() ) 947 rSet.Put(SfxStringItem( 948 nWhich, String(SfxResId(STR_SAVEDOC)))); 949 else 950 rSet.DisableItem(nWhich); 951 } 952 break; 953 954 case SID_DOCINFO: 955 if ( 0 != ( pImp->eFlags & SFXOBJECTSHELL_NODOCINFO ) ) 956 rSet.DisableItem( nWhich ); 957 break; 958 959 case SID_CLOSEDOC: 960 { 961 SfxObjectShell *pDoc = this; 962 SfxViewFrame *pFrame = GetFrame(); 963 if ( pFrame && pFrame->GetFrame().GetParentFrame() ) 964 { 965 // Wenn SID_CLOSEDOC "uber Menue etc. ausgef"uhrt wird, das 966 // aktuelle Dokument aber in einem Frame liegt, soll eigentlich 967 // das FrameSetDocument geclosed werden 968 pDoc = pFrame->GetTopViewFrame()->GetObjectShell(); 969 } 970 971 if ( pDoc->GetFlags() & SFXOBJECTSHELL_DONTCLOSE ) 972 rSet.DisableItem(nWhich); 973 else 974 rSet.Put(SfxStringItem(nWhich, String(SfxResId(STR_CLOSEDOC)))); 975 break; 976 } 977 978 case SID_SAVEASDOC: 979 { 980 if( ( pImp->nLoadedFlags & SFX_LOADED_MAINDOCUMENT ) != SFX_LOADED_MAINDOCUMENT ) 981 { 982 rSet.DisableItem( nWhich ); 983 break; 984 } 985 /* 986 const SfxFilter* pCombinedFilters = NULL; 987 SfxFilterContainer* pFilterContainer = GetFactory().GetFilterContainer(); 988 989 if ( pFilterContainer ) 990 { 991 SfxFilterFlags nMust = SFX_FILTER_IMPORT | SFX_FILTER_EXPORT; 992 SfxFilterFlags nDont = SFX_FILTER_NOTINSTALLED | SFX_FILTER_INTERNAL; 993 994 pCombinedFilters = pFilterContainer->GetAnyFilter( nMust, nDont ); 995 } 996 */ 997 if ( /*!pCombinedFilters ||*/ !GetMedium() ) 998 rSet.DisableItem( nWhich ); 999 else 1000 rSet.Put( SfxStringItem( nWhich, String( SfxResId( STR_SAVEASDOC ) ) ) ); 1001 break; 1002 } 1003 1004 case SID_EXPORTDOCASPDF: 1005 case SID_DIRECTEXPORTDOCASPDF: 1006 { 1007 /* 1008 1009 search for filter cant work correctly ... 1010 Because it's not clear, which export filter for which office module 1011 must be searched. On the other side it can be very expensive doing so. 1012 The best solution would be: on installation time we should know if pdf feature 1013 was installed or not!!! (e.g. by writing a bool inside cfg) 1014 1015 SfxFilterContainer* pFilterContainer = GetFactory().GetFilterContainer(); 1016 if ( pFilterContainer ) 1017 { 1018 String aPDFExtension = String::CreateFromAscii( "pdf" ); 1019 const SfxFilter* pFilter = pFilterContainer->GetFilter4Extension( aPDFExtension, SFX_FILTER_EXPORT ); 1020 if ( pFilter != NULL ) 1021 break; 1022 } 1023 1024 rSet.DisableItem( nWhich ); 1025 */ 1026 break; 1027 } 1028 1029 case SID_DOC_MODIFIED: 1030 { 1031 rSet.Put( SfxStringItem( SID_DOC_MODIFIED, IsModified() ? '*' : ' ' ) ); 1032 break; 1033 } 1034 1035 case SID_MODIFIED: 1036 { 1037 rSet.Put( SfxBoolItem( SID_MODIFIED, IsModified() ) ); 1038 break; 1039 } 1040 1041 case SID_DOCINFO_TITLE: 1042 { 1043 rSet.Put( SfxStringItem( 1044 SID_DOCINFO_TITLE, getDocProperties()->getTitle() ) ); 1045 break; 1046 } 1047 case SID_FILE_NAME: 1048 { 1049 if( GetMedium() && HasName() ) 1050 rSet.Put( SfxStringItem( 1051 SID_FILE_NAME, GetMedium()->GetName() ) ); 1052 break; 1053 } 1054 case SID_SIGNATURE: 1055 { 1056 rSet.Put( SfxUInt16Item( SID_SIGNATURE, GetDocumentSignatureState() ) ); 1057 break; 1058 } 1059 case SID_MACRO_SIGNATURE: 1060 { 1061 // the slot makes sense only if there is a macro in the document 1062 if ( pImp->documentStorageHasMacros() || pImp->aMacroMode.hasMacroLibrary() ) 1063 rSet.Put( SfxUInt16Item( SID_MACRO_SIGNATURE, GetScriptingSignatureState() ) ); 1064 else 1065 rSet.DisableItem( nWhich ); 1066 break; 1067 } 1068 } 1069 } 1070 } 1071 1072 //-------------------------------------------------------------------- 1073 1074 void SfxObjectShell::ExecProps_Impl(SfxRequest &rReq) 1075 { 1076 switch ( rReq.GetSlot() ) 1077 { 1078 case SID_MODIFIED: 1079 { 1080 SetModified( ( (SfxBoolItem&) rReq.GetArgs()->Get(SID_MODIFIED)).GetValue() ); 1081 rReq.Done(); 1082 break; 1083 } 1084 1085 case SID_DOCTITLE: 1086 SetTitle( ( (SfxStringItem&) rReq.GetArgs()->Get(SID_DOCTITLE)).GetValue() ); 1087 rReq.Done(); 1088 break; 1089 1090 case SID_DOCINFO_AUTHOR : 1091 { 1092 ::rtl::OUString aStr = ( (SfxStringItem&)rReq.GetArgs()->Get(rReq.GetSlot())).GetValue(); 1093 getDocProperties()->setAuthor( aStr ); 1094 break; 1095 } 1096 1097 case SID_DOCINFO_COMMENTS : 1098 { 1099 ::rtl::OUString aStr = ( (SfxStringItem&)rReq.GetArgs()->Get(rReq.GetSlot())).GetValue(); 1100 getDocProperties()->setDescription( aStr ); 1101 break; 1102 } 1103 1104 case SID_DOCINFO_KEYWORDS : 1105 { 1106 ::rtl::OUString aStr = ( (SfxStringItem&)rReq.GetArgs()->Get(rReq.GetSlot())).GetValue(); 1107 getDocProperties()->setKeywords( 1108 ::comphelper::string::convertCommaSeparated(aStr) ); 1109 break; 1110 } 1111 } 1112 } 1113 1114 //-------------------------------------------------------------------- 1115 1116 void SfxObjectShell::StateProps_Impl(SfxItemSet &rSet) 1117 { 1118 SfxWhichIter aIter(rSet); 1119 for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() ) 1120 { 1121 switch ( nSID ) 1122 { 1123 case SID_DOCINFO_AUTHOR : 1124 { 1125 rSet.Put( SfxStringItem( nSID, 1126 getDocProperties()->getAuthor() ) ); 1127 break; 1128 } 1129 1130 case SID_DOCINFO_COMMENTS : 1131 { 1132 rSet.Put( SfxStringItem( nSID, 1133 getDocProperties()->getDescription()) ); 1134 break; 1135 } 1136 1137 case SID_DOCINFO_KEYWORDS : 1138 { 1139 rSet.Put( SfxStringItem( nSID, ::comphelper::string:: 1140 convertCommaSeparated(getDocProperties()->getKeywords())) ); 1141 break; 1142 } 1143 1144 case SID_DOCPATH: 1145 { 1146 DBG_ERROR( "Not supported anymore!" ); 1147 break; 1148 } 1149 1150 case SID_DOCFULLNAME: 1151 { 1152 rSet.Put( SfxStringItem( SID_DOCFULLNAME, GetTitle(SFX_TITLE_FULLNAME) ) ); 1153 break; 1154 } 1155 1156 case SID_DOCTITLE: 1157 { 1158 rSet.Put( SfxStringItem( SID_DOCTITLE, GetTitle() ) ); 1159 break; 1160 } 1161 1162 case SID_DOC_READONLY: 1163 { 1164 rSet.Put( SfxBoolItem( SID_DOC_READONLY, IsReadOnly() ) ); 1165 break; 1166 } 1167 1168 case SID_DOC_SAVED: 1169 { 1170 rSet.Put( SfxBoolItem( SID_DOC_SAVED, !IsModified() ) ); 1171 break; 1172 } 1173 1174 case SID_CLOSING: 1175 { 1176 rSet.Put( SfxBoolItem( SID_CLOSING, false ) ); 1177 break; 1178 } 1179 1180 case SID_DOC_LOADING: 1181 rSet.Put( SfxBoolItem( nSID, SFX_LOADED_MAINDOCUMENT != 1182 ( pImp->nLoadedFlags & SFX_LOADED_MAINDOCUMENT ) ) ); 1183 break; 1184 1185 case SID_IMG_LOADING: 1186 rSet.Put( SfxBoolItem( nSID, SFX_LOADED_IMAGES != 1187 ( pImp->nLoadedFlags & SFX_LOADED_IMAGES ) ) ); 1188 break; 1189 } 1190 } 1191 } 1192 1193 //-------------------------------------------------------------------- 1194 1195 void SfxObjectShell::ExecView_Impl(SfxRequest &rReq) 1196 { 1197 switch ( rReq.GetSlot() ) 1198 { 1199 case SID_ACTIVATE: 1200 { 1201 SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this, sal_True ); 1202 if ( pFrame ) 1203 pFrame->GetFrame().Appear(); 1204 rReq.SetReturnValue( SfxObjectItem( 0, pFrame ) ); 1205 rReq.Done(); 1206 break; 1207 } 1208 case SID_NEWWINDOWFOREDIT: 1209 { 1210 SfxViewFrame* pFrame = SfxViewFrame::Current(); 1211 if( pFrame->GetObjectShell() == this && 1212 ( pFrame->GetFrameType() & SFXFRAME_HASTITLE ) ) 1213 pFrame->ExecuteSlot( rReq ); 1214 else 1215 { 1216 String aFileName( GetObjectShell()->GetMedium()->GetName() ); 1217 if ( aFileName.Len() ) 1218 { 1219 SfxStringItem aName( SID_FILE_NAME, aFileName ); 1220 SfxBoolItem aCreateView( SID_OPEN_NEW_VIEW, sal_True ); 1221 SFX_APP()->GetAppDispatcher_Impl()->Execute( 1222 SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, &aName, 1223 &aCreateView, 0L); 1224 } 1225 } 1226 } 1227 } 1228 } 1229 1230 //-------------------------------------------------------------------- 1231 1232 void SfxObjectShell::StateView_Impl(SfxItemSet& /*rSet*/) 1233 { 1234 } 1235 1236 sal_uInt16 SfxObjectShell::ImplCheckSignaturesInformation( const uno::Sequence< security::DocumentSignatureInformation >& aInfos ) 1237 { 1238 sal_Bool bCertValid = sal_True; 1239 sal_uInt16 nResult = SIGNATURESTATE_NOSIGNATURES; 1240 int nInfos = aInfos.getLength(); 1241 bool bCompleteSignature = true; 1242 if( nInfos ) 1243 { 1244 nResult = SIGNATURESTATE_SIGNATURES_OK; 1245 for ( int n = 0; n < nInfos; n++ ) 1246 { 1247 if ( bCertValid ) 1248 { 1249 sal_Int32 nCertStat = aInfos[n].CertificateStatus; 1250 bCertValid = nCertStat == security::CertificateValidity::VALID ? sal_True : sal_False; 1251 } 1252 1253 if ( !aInfos[n].SignatureIsValid ) 1254 { 1255 nResult = SIGNATURESTATE_SIGNATURES_BROKEN; 1256 break; // we know enough 1257 } 1258 bCompleteSignature &= !aInfos[n].PartialDocumentSignature; 1259 } 1260 } 1261 1262 if ( nResult == SIGNATURESTATE_SIGNATURES_OK && !bCertValid ) 1263 nResult = SIGNATURESTATE_SIGNATURES_NOTVALIDATED; 1264 else if ( nResult == SIGNATURESTATE_SIGNATURES_OK && bCertValid && !bCompleteSignature) 1265 nResult = SIGNATURESTATE_SIGNATURES_PARTIAL_OK; 1266 1267 // this code must not check whether the document is modified 1268 // it should only check the provided info 1269 1270 return nResult; 1271 } 1272 1273 uno::Sequence< security::DocumentSignatureInformation > SfxObjectShell::ImplAnalyzeSignature( sal_Bool bScriptingContent, const uno::Reference< security::XDocumentDigitalSignatures >& xSigner ) 1274 { 1275 uno::Sequence< security::DocumentSignatureInformation > aResult; 1276 uno::Reference< security::XDocumentDigitalSignatures > xLocSigner = xSigner; 1277 1278 if ( GetMedium() && GetMedium()->GetName().Len() && IsOwnStorageFormat_Impl( *GetMedium()) && GetMedium()->GetStorage().is() ) 1279 { 1280 try 1281 { 1282 if ( !xLocSigner.is() ) 1283 { 1284 uno::Sequence< uno::Any > aArgs( 1 ); 1285 aArgs[0] <<= ::rtl::OUString(); 1286 try 1287 { 1288 uno::Reference < beans::XPropertySet > xPropSet( GetStorage(), uno::UNO_QUERY_THROW ); 1289 aArgs[0] = xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ); 1290 } 1291 catch( uno::Exception& ) 1292 { 1293 } 1294 1295 xLocSigner.set( comphelper::getProcessServiceFactory()->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ), aArgs ), uno::UNO_QUERY_THROW ); 1296 1297 } 1298 1299 if ( bScriptingContent ) 1300 aResult = xLocSigner->verifyScriptingContentSignatures( GetMedium()->GetZipStorageToSign_Impl(), 1301 uno::Reference< io::XInputStream >() ); 1302 else 1303 aResult = xLocSigner->verifyDocumentContentSignatures( GetMedium()->GetZipStorageToSign_Impl(), 1304 uno::Reference< io::XInputStream >() ); 1305 } 1306 catch( com::sun::star::uno::Exception& ) 1307 { 1308 } 1309 } 1310 1311 return aResult; 1312 } 1313 1314 sal_uInt16 SfxObjectShell::ImplGetSignatureState( sal_Bool bScriptingContent ) 1315 { 1316 sal_Int16* pState = bScriptingContent ? &pImp->nScriptingSignatureState : &pImp->nDocumentSignatureState; 1317 1318 if ( *pState == SIGNATURESTATE_UNKNOWN ) 1319 { 1320 *pState = SIGNATURESTATE_NOSIGNATURES; 1321 1322 uno::Sequence< security::DocumentSignatureInformation > aInfos = ImplAnalyzeSignature( bScriptingContent ); 1323 *pState = ImplCheckSignaturesInformation( aInfos ); 1324 } 1325 1326 if ( *pState == SIGNATURESTATE_SIGNATURES_OK || *pState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED 1327 || *pState == SIGNATURESTATE_SIGNATURES_PARTIAL_OK) 1328 { 1329 if ( IsModified() ) 1330 *pState = SIGNATURESTATE_SIGNATURES_INVALID; 1331 } 1332 1333 return (sal_uInt16)*pState; 1334 } 1335 1336 void SfxObjectShell::ImplSign( sal_Bool bScriptingContent ) 1337 { 1338 // Check if it is stored in OASIS format... 1339 if ( GetMedium() 1340 && GetMedium()->GetFilter() 1341 && GetMedium()->GetName().Len() 1342 && ( !GetMedium()->GetFilter()->IsOwnFormat() 1343 || !GetMedium()->HasStorage_Impl() 1344 ) 1345 ) 1346 { 1347 // Only OASIS and OOo6.x formats will be handled further 1348 InfoBox( NULL, SfxResId( RID_XMLSEC_INFO_WRONGDOCFORMAT ) ).Execute(); 1349 return; 1350 } 1351 1352 // check whether the document is signed 1353 ImplGetSignatureState( sal_False ); // document signature 1354 ImplGetSignatureState( sal_True ); // script signature 1355 sal_Bool bHasSign = ( pImp->nScriptingSignatureState != SIGNATURESTATE_NOSIGNATURES || pImp->nDocumentSignatureState != SIGNATURESTATE_NOSIGNATURES ); 1356 1357 // the target ODF version on saving 1358 SvtSaveOptions aSaveOpt; 1359 SvtSaveOptions::ODFDefaultVersion nVersion = aSaveOpt.GetODFDefaultVersion(); 1360 1361 // the document is not new and is not modified 1362 ::rtl::OUString aODFVersion; 1363 try 1364 { 1365 // check the version of the document 1366 uno::Reference < beans::XPropertySet > xPropSet( GetStorage(), uno::UNO_QUERY_THROW ); 1367 xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ) >>= aODFVersion; 1368 } 1369 catch( uno::Exception& ) 1370 {} 1371 1372 bool bNoSig = false; 1373 1374 if ( IsModified() || !GetMedium() || !GetMedium()->GetName().Len() 1375 || (!aODFVersion.equals( ODFVER_012_TEXT ) && !bHasSign) ) 1376 { 1377 // the document might need saving ( new, modified or in ODF1.1 format without signature ) 1378 1379 if ( nVersion >= SvtSaveOptions::ODFVER_012 ) 1380 { 1381 1382 if ( (bHasSign && QueryBox( NULL, SfxResId( MSG_XMLSEC_QUERY_SAVESIGNEDBEFORESIGN ) ).Execute() == RET_YES) 1383 || (!bHasSign && QueryBox( NULL, SfxResId( RID_XMLSEC_QUERY_SAVEBEFORESIGN ) ).Execute() == RET_YES) ) 1384 { 1385 sal_uInt16 nId = SID_SAVEDOC; 1386 if ( !GetMedium() || !GetMedium()->GetName().Len() ) 1387 nId = SID_SAVEASDOC; 1388 SfxRequest aSaveRequest( nId, 0, GetPool() ); 1389 //ToDo: Review. We needed to call SetModified, otherwise the document would not be saved. 1390 SetModified(sal_True); 1391 ExecFile_Impl( aSaveRequest ); 1392 1393 // Check if it is stored in OASIS format... 1394 if ( GetMedium() && GetMedium()->GetFilter() 1395 && ( !GetMedium()->GetFilter()->IsOwnFormat() || !GetMedium()->HasStorage_Impl() 1396 || SotStorage::GetVersion( GetMedium()->GetStorage() ) <= SOFFICE_FILEFORMAT_60 ) ) 1397 { 1398 // Only OASIS format will be handled further 1399 InfoBox( NULL, SfxResId( RID_XMLSEC_INFO_WRONGDOCFORMAT ) ).Execute(); 1400 return; 1401 } 1402 } 1403 else 1404 { 1405 //When the document is modified then we must not show the digital signatures dialog 1406 //If we have come here then the user denied to save. 1407 if (!bHasSign) 1408 bNoSig = true; 1409 } 1410 } 1411 else 1412 { 1413 ErrorBox( NULL, WB_OK, SfxResId( STR_XMLSEC_ODF12_EXPECTED ) ).Execute(); 1414 return; 1415 } 1416 1417 if ( IsModified() || !GetMedium() || !GetMedium()->GetName().Len() ) 1418 return; 1419 } 1420 1421 // the document is not modified currently, so it can not become modified after signing 1422 sal_Bool bAllowModifiedBack = sal_False; 1423 if ( IsEnableSetModified() ) 1424 { 1425 EnableSetModified( sal_False ); 1426 bAllowModifiedBack = sal_True; 1427 } 1428 1429 // we have to store to the original document, the original medium should be closed for this time 1430 if ( !bNoSig 1431 && ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) ) 1432 { 1433 GetMedium()->CloseAndRelease(); 1434 1435 // We sign only ODF1.2, that means that if this point has been reached, 1436 // the ODF1.2 signing process should be used. 1437 // This code still might be called to show the signature of ODF1.1 document. 1438 sal_Bool bSigned = GetMedium()->SignContents_Impl( 1439 bScriptingContent, 1440 aODFVersion, 1441 pImp->nDocumentSignatureState == SIGNATURESTATE_SIGNATURES_OK 1442 || pImp->nDocumentSignatureState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED 1443 || pImp->nDocumentSignatureState == SIGNATURESTATE_SIGNATURES_PARTIAL_OK); 1444 1445 DoSaveCompleted( GetMedium() ); 1446 1447 if ( bSigned ) 1448 { 1449 if ( bScriptingContent ) 1450 { 1451 pImp->nScriptingSignatureState = SIGNATURESTATE_UNKNOWN;// Re-Check 1452 1453 // adding of scripting signature removes existing document signature 1454 pImp->nDocumentSignatureState = SIGNATURESTATE_UNKNOWN;// Re-Check 1455 } 1456 else 1457 pImp->nDocumentSignatureState = SIGNATURESTATE_UNKNOWN;// Re-Check 1458 1459 pImp->bSignatureErrorIsShown = sal_False; 1460 1461 Invalidate( SID_SIGNATURE ); 1462 Invalidate( SID_MACRO_SIGNATURE ); 1463 Broadcast( SfxSimpleHint(SFX_HINT_TITLECHANGED) ); 1464 } 1465 } 1466 1467 if ( bAllowModifiedBack ) 1468 EnableSetModified( sal_True ); 1469 } 1470 1471 sal_uInt16 SfxObjectShell::GetDocumentSignatureState() 1472 { 1473 return ImplGetSignatureState( sal_False ); 1474 } 1475 1476 void SfxObjectShell::SignDocumentContent() 1477 { 1478 ImplSign( sal_False ); 1479 } 1480 1481 sal_uInt16 SfxObjectShell::GetScriptingSignatureState() 1482 { 1483 return ImplGetSignatureState( sal_True ); 1484 } 1485 1486 void SfxObjectShell::SignScriptingContent() 1487 { 1488 ImplSign( sal_True ); 1489 } 1490 1491 // static 1492 const uno::Sequence<sal_Int8>& SfxObjectShell::getUnoTunnelId() 1493 { 1494 static uno::Sequence<sal_Int8> * pSeq = 0; 1495 if( !pSeq ) 1496 { 1497 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 1498 if( !pSeq ) 1499 { 1500 static uno::Sequence< sal_Int8 > aSeq( 16 ); 1501 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); 1502 pSeq = &aSeq; 1503 } 1504 } 1505 return *pSeq; 1506 } 1507