1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
23 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
24 #include <com/sun/star/util/CloseVetoException.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/beans/PropertyValue.hpp>
27 #include <com/sun/star/beans/PropertyAttribute.hpp>
28 #include <com/sun/star/document/XCmisDocument.hpp>
29 #include <com/sun/star/drawing/LineStyle.hpp>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <com/sun/star/security/XCertificate.hpp>
32 #include <com/sun/star/task/ErrorCodeIOException.hpp>
33 #include <com/sun/star/task/InteractionHandler.hpp>
34 #include <com/sun/star/task/XStatusIndicator.hpp>
35 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
36 #include <comphelper/processfactory.hxx>
37 #include <comphelper/servicehelper.hxx>
38 #include <com/sun/star/drawing/XDrawView.hpp>
40 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
41 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
42 #include <comphelper/diagnose_ex.hxx>
43 #include <tools/urlobj.hxx>
44 #include <svl/whiter.hxx>
45 #include <svl/intitem.hxx>
46 #include <svl/eitem.hxx>
47 #include <svl/visitem.hxx>
48 #include <svtools/sfxecode.hxx>
49 #include <svtools/ehdl.hxx>
50 #include <sal/log.hxx>
51 #include <sfx2/app.hxx>
53 #include <comphelper/string.hxx>
54 #include <basic/sbxcore.hxx>
55 #include <basic/sberrors.hxx>
56 #include <unotools/moduleoptions.hxx>
57 #include <unotools/saveopt.hxx>
58 #include <unotools/securityoptions.hxx>
59 #include <svtools/DocumentToGraphicRenderer.hxx>
60 #include <vcl/gdimtf.hxx>
61 #include <vcl/svapp.hxx>
62 #include <vcl/weld.hxx>
63 #include <comphelper/documentconstants.hxx>
64 #include <comphelper/storagehelper.hxx>
65 #include <comphelper/lok.hxx>
66 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
67 #include <tools/link.hxx>
68 #include <svl/cryptosign.hxx>
70 #include <sfx2/signaturestate.hxx>
71 #include <sfx2/sfxresid.hxx>
72 #include <sfx2/request.hxx>
73 #include <sfx2/printer.hxx>
74 #include <sfx2/viewsh.hxx>
75 #include <sfx2/dinfdlg.hxx>
76 #include <sfx2/docfilt.hxx>
77 #include <sfx2/docfile.hxx>
78 #include <sfx2/dispatch.hxx>
79 #include <sfx2/objitem.hxx>
80 #include <sfx2/objsh.hxx>
81 #include <objshimp.hxx>
82 #include <sfx2/module.hxx>
83 #include <sfx2/viewfrm.hxx>
84 #include <versdlg.hxx>
85 #include <sfx2/strings.hrc>
86 #include <sfx2/docfac.hxx>
87 #include <sfx2/fcontnr.hxx>
88 #include <sfx2/msgpool.hxx>
89 #include <sfx2/objface.hxx>
90 #include <checkin.hxx>
91 #include <sfx2/infobar.hxx>
92 #include <sfx2/sfxuno.hxx>
93 #include <sfx2/sfxsids.hrc>
94 #include <sfx2/lokhelper.hxx>
95 #include <SfxRedactionHelper.hxx>
97 #include <com/sun/star/util/XCloseable.hpp>
98 #include <com/sun/star/document/XDocumentProperties.hpp>
100 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
101 #include <com/sun/star/frame/XDesktop2.hpp>
102 #include <com/sun/star/frame/Desktop.hpp>
104 #include <guisaveas.hxx>
105 #include <saveastemplatedlg.hxx>
107 #include <cppuhelper/implbase.hxx>
108 #include <unotools/ucbstreamhelper.hxx>
109 #include <unotools/streamwrap.hxx>
110 #include <comphelper/sequenceashashmap.hxx>
111 #include <editeng/unoprnms.hxx>
112 #include <comphelper/base64.hxx>
114 #include <autoredactdialog.hxx>
116 #include <boost/property_tree/json_parser.hpp>
118 #define ShellClass_SfxObjectShell
119 #include <sfxslots.hxx>
121 using namespace ::com::sun::star
;
122 using namespace ::com::sun::star::lang
;
123 using namespace ::com::sun::star::uno
;
124 using namespace ::com::sun::star::awt
;
125 using namespace ::com::sun::star::container
;
126 using namespace ::com::sun::star::beans
;
127 using namespace ::com::sun::star::document
;
128 using namespace ::com::sun::star::security
;
129 using namespace ::com::sun::star::task
;
130 using namespace ::com::sun::star::graphic
;
132 SFX_IMPL_SUPERCLASS_INTERFACE(SfxObjectShell
, SfxShell
)
134 void SfxObjectShell::InitInterface_Impl()
140 class SfxClosePreventer_Impl
: public ::cppu::WeakImplHelper
< css::util::XCloseListener
>
142 bool m_bGotOwnership
;
143 bool m_bPreventClose
;
146 SfxClosePreventer_Impl();
148 bool HasOwnership() const { return m_bGotOwnership
; }
150 void SetPreventClose( bool bPrevent
) { m_bPreventClose
= bPrevent
; }
152 virtual void SAL_CALL
queryClosing( const lang::EventObject
& aEvent
, sal_Bool bDeliverOwnership
) override
;
154 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& aEvent
) override
;
156 virtual void SAL_CALL
disposing( const lang::EventObject
& aEvent
) override
;
162 SfxClosePreventer_Impl::SfxClosePreventer_Impl()
163 : m_bGotOwnership( false )
164 , m_bPreventClose( true )
168 void SAL_CALL
SfxClosePreventer_Impl::queryClosing( const lang::EventObject
&, sal_Bool bDeliverOwnership
)
170 if ( m_bPreventClose
)
172 if ( !m_bGotOwnership
)
173 m_bGotOwnership
= bDeliverOwnership
;
175 throw util::CloseVetoException();
179 void SAL_CALL
SfxClosePreventer_Impl::notifyClosing( const lang::EventObject
& )
182 void SAL_CALL
SfxClosePreventer_Impl::disposing( const lang::EventObject
& )
187 class SfxInstanceCloseGuard_Impl
189 rtl::Reference
<SfxClosePreventer_Impl
> m_xPreventer
;
190 uno::Reference
< util::XCloseable
> m_xCloseable
;
193 SfxInstanceCloseGuard_Impl() {}
195 ~SfxInstanceCloseGuard_Impl();
197 bool Init_Impl( const uno::Reference
< util::XCloseable
>& xCloseable
);
202 bool SfxInstanceCloseGuard_Impl::Init_Impl( const uno::Reference
< util::XCloseable
>& xCloseable
)
204 bool bResult
= false;
206 // do not allow reinit after the successful init
207 if ( xCloseable
.is() && !m_xCloseable
.is() )
211 m_xPreventer
= new SfxClosePreventer_Impl();
212 xCloseable
->addCloseListener( m_xPreventer
);
213 m_xCloseable
= xCloseable
;
216 catch( uno::Exception
& )
218 OSL_FAIL( "Could not register close listener!" );
225 SfxInstanceCloseGuard_Impl::~SfxInstanceCloseGuard_Impl()
227 if ( !m_xCloseable
.is() || !m_xPreventer
.is() )
232 m_xCloseable
->removeCloseListener( m_xPreventer
);
234 catch( uno::Exception
& )
240 if ( m_xPreventer
.is() )
242 m_xPreventer
->SetPreventClose( false );
244 if ( m_xPreventer
->HasOwnership() )
245 m_xCloseable
->close( true ); // TODO: do it asynchronously
248 catch( uno::Exception
& )
254 void SfxObjectShell::PrintExec_Impl(SfxRequest
&rReq
)
256 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst(this);
259 rReq
.SetSlot( SID_PRINTDOC
);
260 pFrame
->GetViewShell()->ExecuteSlot(rReq
);
265 void SfxObjectShell::PrintState_Impl(SfxItemSet
&rSet
)
267 bool bPrinting
= false;
268 SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst( this );
271 SfxPrinter
*pPrinter
= pFrame
->GetViewShell()->GetPrinter();
272 bPrinting
= pPrinter
&& pPrinter
->IsPrinting();
274 rSet
.Put( SfxBoolItem( SID_PRINTOUT
, bPrinting
) );
277 bool SfxObjectShell::APISaveAs_Impl(std::u16string_view aFileName
, SfxItemSet
& rItemSet
,
278 const css::uno::Sequence
<css::beans::PropertyValue
>& rArgs
)
284 OUString aFilterName
;
285 const SfxStringItem
* pFilterNameItem
= rItemSet
.GetItem
<SfxStringItem
>(SID_FILTER_NAME
, false);
286 if( pFilterNameItem
)
288 aFilterName
= pFilterNameItem
->GetValue();
292 const SfxStringItem
* pContentTypeItem
= rItemSet
.GetItem
<SfxStringItem
>(SID_CONTENTTYPE
, false);
293 if ( pContentTypeItem
)
295 std::shared_ptr
<const SfxFilter
> pFilter
= SfxFilterMatcher( GetFactory().GetFactoryName() ).GetFilter4Mime( pContentTypeItem
->GetValue(), SfxFilterFlags::EXPORT
);
297 aFilterName
= pFilter
->GetName();
301 // in case no filter defined use default one
302 if( aFilterName
.isEmpty() )
304 std::shared_ptr
<const SfxFilter
> pFilt
= SfxFilter::GetDefaultFilterFromFactory(GetFactory().GetFactoryName());
306 DBG_ASSERT( pFilt
, "No default filter!\n" );
308 aFilterName
= pFilt
->GetFilterName();
310 rItemSet
.Put(SfxStringItem(SID_FILTER_NAME
, aFilterName
));
315 SfxObjectShellRef
xLock( this ); // ???
317 // use the title that is provided in the media descriptor
318 const SfxStringItem
* pDocTitleItem
= rItemSet
.GetItem
<SfxStringItem
>(SID_DOCINFO_TITLE
, false);
320 getDocProperties()->setTitle( pDocTitleItem
->GetValue() );
322 bOk
= CommonSaveAs_Impl(INetURLObject(aFileName
), aFilterName
, rItemSet
, rArgs
);
329 void SfxObjectShell::CheckOut( )
333 uno::Reference
< document::XCmisDocument
> xCmisDoc( GetModel(), uno::UNO_QUERY_THROW
);
334 xCmisDoc
->checkOut( );
336 // Remove the info bar
337 if (SfxViewFrame
* pViewFrame
= GetFrame())
338 pViewFrame
->RemoveInfoBar( u
"checkout" );
340 catch ( const uno::RuntimeException
& e
)
342 if (SfxViewFrame
* pFrame
= GetFrame())
344 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(pFrame
->GetFrameWeld(),
345 VclMessageType::Warning
, VclButtonsType::Ok
, e
.Message
));
351 void SfxObjectShell::CancelCheckOut( )
355 uno::Reference
< document::XCmisDocument
> xCmisDoc( GetModel(), uno::UNO_QUERY_THROW
);
356 xCmisDoc
->cancelCheckOut( );
358 uno::Reference
< util::XModifiable
> xModifiable( GetModel( ), uno::UNO_QUERY
);
359 if ( xModifiable
.is( ) )
360 xModifiable
->setModified( false );
362 catch ( const uno::RuntimeException
& e
)
364 if (SfxViewFrame
* pFrame
= GetFrame())
366 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(pFrame
->GetFrameWeld(),
367 VclMessageType::Warning
, VclButtonsType::Ok
, e
.Message
));
373 void SfxObjectShell::CheckIn( )
377 uno::Reference
< document::XCmisDocument
> xCmisDoc( GetModel(), uno::UNO_QUERY_THROW
);
378 // Pop up dialog to ask for comment and major
379 if (SfxViewFrame
* pFrame
= GetFrame())
381 SfxCheckinDialog
checkinDlg(pFrame
->GetFrameWeld());
382 if (checkinDlg
.run() == RET_OK
)
384 xCmisDoc
->checkIn(checkinDlg
.IsMajor(), checkinDlg
.GetComment());
385 uno::Reference
< util::XModifiable
> xModifiable( GetModel( ), uno::UNO_QUERY
);
386 if ( xModifiable
.is( ) )
387 xModifiable
->setModified( false );
391 catch ( const uno::RuntimeException
& e
)
393 if (SfxViewFrame
* pFrame
= GetFrame())
395 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(pFrame
->GetFrameWeld(),
396 VclMessageType::Warning
, VclButtonsType::Ok
, e
.Message
));
402 uno::Sequence
< document::CmisVersion
> SfxObjectShell::GetCmisVersions( ) const
406 uno::Reference
< document::XCmisDocument
> xCmisDoc( GetModel(), uno::UNO_QUERY_THROW
);
407 return xCmisDoc
->getAllVersions( );
409 catch ( const uno::RuntimeException
& e
)
411 if (SfxViewFrame
* pFrame
= GetFrame())
413 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(pFrame
->GetFrameWeld(),
414 VclMessageType::Warning
, VclButtonsType::Ok
, e
.Message
));
418 return uno::Sequence
< document::CmisVersion
> ( );
421 bool SfxObjectShell::IsSignPDF() const
423 if (pMedium
&& !pMedium
->IsOriginallyReadOnly())
425 const std::shared_ptr
<const SfxFilter
>& pFilter
= pMedium
->GetFilter();
426 if (pFilter
&& pFilter
->GetName() == "draw_pdf_import")
433 uno::Reference
<security::XCertificate
> SfxObjectShell::GetSignPDFCertificate() const
435 uno::Reference
<frame::XModel
> xModel
= GetBaseModel();
438 return uno::Reference
<security::XCertificate
>();
441 uno::Reference
<drawing::XShapes
> xShapes(xModel
->getCurrentSelection(), uno::UNO_QUERY
);
442 if (!xShapes
.is() || xShapes
->getCount() < 1)
444 return uno::Reference
<security::XCertificate
>();
447 uno::Reference
<beans::XPropertySet
> xShapeProps(xShapes
->getByIndex(0), uno::UNO_QUERY
);
448 if (!xShapeProps
.is())
450 return uno::Reference
<security::XCertificate
>();
453 if (!xShapeProps
->getPropertySetInfo()->hasPropertyByName(u
"InteropGrabBag"_ustr
))
455 return uno::Reference
<security::XCertificate
>();
458 comphelper::SequenceAsHashMap
aMap(xShapeProps
->getPropertyValue(u
"InteropGrabBag"_ustr
));
459 auto it
= aMap
.find(u
"SignatureCertificate"_ustr
);
460 if (it
== aMap
.end())
462 return uno::Reference
<security::XCertificate
>();
465 return uno::Reference
<security::XCertificate
>(it
->second
, uno::UNO_QUERY
);
468 static void sendErrorToLOK(const ErrCodeMsg
& error
)
470 if (error
.GetCode().GetClass() == ErrCodeClass::NONE
)
473 SfxViewShell
* pNotifier
= SfxViewShell::Current();
477 boost::property_tree::ptree aTree
;
478 aTree
.put("code", error
);
479 aTree
.put("kind", "");
480 aTree
.put("cmd", "");
483 if (ErrorStringFactory::CreateString(error
, aErr
))
484 aTree
.put("message", aErr
.toUtf8());
486 std::stringstream aStream
;
487 boost::property_tree::write_json(aStream
, aTree
);
489 pNotifier
->libreOfficeKitViewCallback(LOK_CALLBACK_ERROR
, OString(aStream
.str()));
494 void SetDocProperties(const uno::Reference
<document::XDocumentProperties
>& xDP
,
495 const uno::Sequence
<beans::PropertyValue
>& rUpdatedProperties
)
497 comphelper::SequenceAsHashMap
aMap(rUpdatedProperties
);
498 OUString aNamePrefix
;
499 auto it
= aMap
.find(u
"NamePrefix"_ustr
);
500 if (it
!= aMap
.end())
502 it
->second
>>= aNamePrefix
;
505 uno::Sequence
<beans::PropertyValue
> aUserDefinedProperties
;
506 it
= aMap
.find(u
"UserDefinedProperties"_ustr
);
507 if (it
!= aMap
.end())
509 it
->second
>>= aUserDefinedProperties
;
512 uno::Reference
<beans::XPropertyContainer
> xUDP
= xDP
->getUserDefinedProperties();
513 if (!aNamePrefix
.isEmpty())
515 uno::Reference
<beans::XPropertySet
> xSet(xUDP
, UNO_QUERY
);
516 uno::Reference
<beans::XPropertySetInfo
> xSetInfo
= xSet
->getPropertySetInfo();
517 const uno::Sequence
<beans::Property
> aProperties
= xSetInfo
->getProperties();
518 for (const auto& rProperty
: aProperties
)
520 if (!rProperty
.Name
.startsWith(aNamePrefix
))
525 if (!(rProperty
.Attributes
& beans::PropertyAttribute::REMOVABLE
))
530 xUDP
->removeProperty(rProperty
.Name
);
534 for (const auto& rUserDefinedProperty
: aUserDefinedProperties
)
536 xUDP
->addProperty(rUserDefinedProperty
.Name
, beans::PropertyAttribute::REMOVABLE
,
537 rUserDefinedProperty
.Value
);
542 void SfxObjectShell::AfterSignContent(bool bHaveWeSigned
, weld::Window
* pDialogParent
)
544 if (comphelper::LibreOfficeKit::isActive())
546 // LOK signing certificates are per-view, don't store them in the model.
550 if ( bHaveWeSigned
&& HasValidSignatures() )
552 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog( pDialogParent
,
553 VclMessageType::Question
, VclButtonsType::YesNo
, SfxResId(STR_QUERY_REMEMBERSIGNATURE
)));
554 SetRememberCurrentSignature(xBox
->run() == RET_YES
);
558 void SfxObjectShell::ExecFile_Impl(SfxRequest
&rReq
)
560 weld::Window
* pDialogParent
= rReq
.GetFrameWeld();
563 SfxViewFrame
* pFrame
= GetFrame();
565 pFrame
= SfxViewFrame::GetFirst(this);
567 pDialogParent
= pFrame
->GetFrameWeld();
570 sal_uInt16 nId
= rReq
.GetSlot();
572 bool bHaveWeSigned
= false;
574 if( SID_SIGNATURE
== nId
|| SID_MACRO_SIGNATURE
== nId
)
576 QueryHiddenInformation(HiddenWarningFact::WhenSigning
);
578 if (SID_SIGNATURE
== nId
)
580 uno::Reference
<security::XCertificate
> xCertificate
= GetSignPDFCertificate();
581 if (xCertificate
.is())
584 svl::crypto::SigningContext aSigningContext
;
585 aSigningContext
.m_xCertificate
= std::move(xCertificate
);
586 bHaveWeSigned
|= SignDocumentContentUsingCertificate(aSigningContext
);
588 // Reload to show how the PDF actually looks like after signing. This also
589 // changes "finish signing" on the infobar back to "sign document" as a side
591 if (SfxViewFrame
* pFrame
= GetFrame())
593 // Store current page before reload.
594 SfxAllItemSet
aSet(SfxGetpApp()->GetPool());
595 uno::Reference
<drawing::XDrawView
> xController(
596 GetBaseModel()->getCurrentController(), uno::UNO_QUERY
);
597 uno::Reference
<beans::XPropertySet
> xPage(xController
->getCurrentPage(),
600 xPage
->getPropertyValue(u
"Number"_ustr
) >>= nPage
;
604 aSet
.Put(SfxInt32Item(SID_PAGE_NUMBER
, nPage
- 1));
606 SfxRequest
aReq(SID_RELOAD
, SfxCallMode::SLOT
, aSet
);
607 pFrame
->ExecReload_Impl(aReq
);
612 // See if a signing cert is passed as a parameter: if so, parse that.
613 std::string aSignatureCert
;
614 std::string aSignatureKey
;
615 const SfxStringItem
* pSignatureCert
= rReq
.GetArg
<SfxStringItem
>(FN_PARAM_1
);
618 aSignatureCert
= pSignatureCert
->GetValue().toUtf8();
620 const SfxStringItem
* pSignatureKey
= rReq
.GetArg
<SfxStringItem
>(FN_PARAM_2
);
623 aSignatureKey
= pSignatureKey
->GetValue().toUtf8();
626 // See if an external signature time/value is provided: if so, sign with those
627 // instead of interactive signing via the dialog.
628 svl::crypto::SigningContext aSigningContext
;
629 const SfxStringItem
* pSignatureTime
= rReq
.GetArg
<SfxStringItem
>(FN_PARAM_3
);
632 sal_Int64 nSignatureTime
= pSignatureTime
->GetValue().toInt64();
633 aSigningContext
.m_nSignatureTime
= nSignatureTime
;
635 const SfxStringItem
* pSignatureValue
= rReq
.GetArg
<SfxStringItem
>(FN_PARAM_4
);
638 OUString aSignatureValue
= pSignatureValue
->GetValue();
639 uno::Sequence
<sal_Int8
> aBytes
;
640 comphelper::Base64::decode(aBytes
, aSignatureValue
);
641 aSigningContext
.m_aSignatureValue
.assign(
642 aBytes
.getArray(), aBytes
.getArray() + aBytes
.getLength());
644 if (!aSigningContext
.m_aSignatureValue
.empty())
646 SignDocumentContentUsingCertificate(aSigningContext
);
651 SfxViewFrame
* pFrame
= GetFrame();
652 SfxViewShell
* pViewShell
= pFrame
? pFrame
->GetViewShell() : nullptr;
655 uno::Reference
<security::XCertificate
> xSigningCertificate
;
656 if (!aSignatureCert
.empty() && !aSignatureKey
.empty())
658 xSigningCertificate
= SfxLokHelper::getSigningCertificate(aSignatureCert
, aSignatureKey
);
660 // Always set the signing certificate, to clear data from a previous dispatch.
661 pViewShell
->SetSigningCertificate(xSigningCertificate
);
664 // Async, all code before return has to go into the callback.
665 SignDocumentContent(pDialogParent
, [this, pDialogParent
] (bool bSigned
) {
666 AfterSignContent(bSigned
, pDialogParent
);
673 // Async, all code before return has to go into the callback.
674 SignScriptingContent(pDialogParent
, [this, pDialogParent
] (bool bSigned
) {
675 AfterSignContent(bSigned
, pDialogParent
);
680 AfterSignContent(bHaveWeSigned
, pDialogParent
);
685 if ( !GetMedium() && nId
!= SID_CLOSEDOC
)
691 // this guard is created here to have it destruction at the end of the method
692 SfxInstanceCloseGuard_Impl aModelGuard
;
694 bool bIsPDFExport
= false;
695 bool bIsAutoRedact
= false;
696 bool bIsAsync
= false;
697 std::vector
<std::pair
<RedactionTarget
, OUString
>> aRedactionTargets
;
702 SfxViewFrame
* pFrame
= GetFrame();
704 pFrame
= SfxViewFrame::GetFirst( this );
708 if ( !IsOwnStorageFormat( *GetMedium() ) )
711 SfxVersionDialog
aDlg(pDialogParent
, pFrame
, IsSaveVersionOnClose());
713 SetSaveVersionOnClose(aDlg
.IsSaveVersionOnClose());
718 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
721 const SfxDocumentInfoItem
* pDocInfItem
= rReq
.GetArg
<SfxDocumentInfoItem
>(SID_DOCINFO
);
724 // parameter, e.g. from replayed macro
725 pDocInfItem
->UpdateDocumentInfo(getDocProperties(), true);
726 SetUseUserData( pDocInfItem
->IsUseUserData() );
727 SetUseThumbnailSave( pDocInfItem
->IsUseThumbnailSave() );
729 else if (const SfxUnoAnyItem
* pItem
= rReq
.GetArg
<SfxUnoAnyItem
>(FN_PARAM_1
))
731 uno::Sequence
<beans::PropertyValue
> aUpdatedProperties
;
732 pItem
->GetValue() >>= aUpdatedProperties
;
733 SetDocProperties(getDocProperties(), aUpdatedProperties
);
737 // no argument containing DocInfo; check optional arguments
738 bool bReadOnly
= IsReadOnly();
739 const SfxBoolItem
* pROItem
= rReq
.GetArg
<SfxBoolItem
>(SID_DOC_READONLY
);
741 // override readonly attribute of document
742 // e.g. if a readonly document is saved elsewhere and user asks for editing DocInfo before
743 bReadOnly
= pROItem
->GetValue();
746 const SfxStringItem
* pFileSize
= rReq
.GetArg
<SfxStringItem
>(FN_PARAM_2
);
747 sal_Int64 nFileSize
= pFileSize
? pFileSize
->GetValue().toInt64() : -1;
748 const OUString
aURL( HasName() ? GetMedium()->GetName() : GetFactory().GetFactoryURL() );
750 Reference
< XCmisDocument
> xCmisDoc( GetModel(), uno::UNO_QUERY
);
751 uno::Sequence
< document::CmisProperty
> aCmisProperties
= xCmisDoc
->getCmisProperties();
753 SfxDocumentInfoItem
aDocInfoItem( aURL
, getDocProperties(), aCmisProperties
,
754 IsUseUserData(), IsUseThumbnailSave(), nFileSize
);
755 const SfxPoolItemHolder
aSlotState(GetSlotState(SID_DOCTEMPLATE
));
757 // templates not supported
758 aDocInfoItem
.SetTemplate(false);
760 SfxItemSetFixed
<SID_DOCINFO
, SID_DOCINFO
, SID_DOC_READONLY
, SID_DOC_READONLY
,
761 SID_EXPLORER_PROPS_START
, SID_EXPLORER_PROPS_START
, SID_BASEURL
, SID_BASEURL
>
763 aSet
.Put( aDocInfoItem
);
764 aSet
.Put( SfxBoolItem( SID_DOC_READONLY
, bReadOnly
) );
765 aSet
.Put( SfxStringItem( SID_EXPLORER_PROPS_START
, GetTitle() ) );
766 aSet
.Put( SfxStringItem( SID_BASEURL
, GetMedium()->GetBaseURL() ) );
768 // creating dialog is done via virtual method; application will
769 // add its own statistics page
770 std::shared_ptr
<SfxDocumentInfoDialog
> xDlg(CreateDocumentInfoDialog(rReq
.GetFrameWeld(), aSet
));
771 auto aFunc
= [this, xDlg
, xCmisDoc
, nFileSize
](sal_Int32 nResult
, SfxRequest
& rRequest
)
773 if (RET_OK
== nResult
)
775 const SfxDocumentInfoItem
* pDocInfoItem
= SfxItemSet::GetItem(xDlg
->GetOutputItemSet(), SID_DOCINFO
, false);
778 // user has done some changes to DocumentInfo
779 pDocInfoItem
->UpdateDocumentInfo(getDocProperties());
780 const uno::Sequence
< document::CmisProperty
>& aNewCmisProperties
=
781 pDocInfoItem
->GetCmisProperties( );
782 if ( aNewCmisProperties
.hasElements( ) )
783 xCmisDoc
->updateCmisProperties( aNewCmisProperties
);
784 SetUseUserData( pDocInfoItem
->IsUseUserData() );
785 SetUseThumbnailSave( pDocInfoItem
-> IsUseThumbnailSave() );
786 // add data from dialog for possible recording purpose
787 rRequest
.AppendItem( SfxDocumentInfoItem( GetTitle(),
788 getDocProperties(), aNewCmisProperties
, IsUseUserData(), IsUseThumbnailSave(), nFileSize
) );
794 // nothing done; no recording
799 if (!rReq
.IsSynchronCall())
801 std::shared_ptr
<SfxRequest
> xReq
= std::make_shared
<SfxRequest
>(rReq
);
802 SfxTabDialogController::runAsync(xDlg
, [xReq
=std::move(xReq
), aFunc
=std::move(aFunc
)](sal_Int32 nResult
)
804 aFunc(nResult
, *xReq
);
810 aFunc(xDlg
->run(), rReq
);
817 case SID_AUTOREDACTDOC
:
819 // Actual redaction takes place on a newly generated Draw document
820 if (!SvtModuleOptions().IsDrawInstalled())
822 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(
823 pDialogParent
, VclMessageType::Warning
, VclButtonsType::Ok
,
824 SfxResId(STR_REDACTION_NO_DRAW_WARNING
)));
831 SfxAutoRedactDialog
aDlg(pDialogParent
);
832 sal_Int16 nResult
= aDlg
.run();
834 if (nResult
!= RET_OK
|| !aDlg
.hasTargets() || !aDlg
.isValidState())
840 // else continue with normal redaction
841 bIsAutoRedact
= true;
842 aDlg
.getTargets(aRedactionTargets
);
849 css::uno::Reference
<css::frame::XModel
> xModel
= GetModel();
853 uno::Reference
< lang::XComponent
> xSourceDoc( xModel
);
855 // Actual redaction takes place on a newly generated Draw document
856 if (!SvtModuleOptions().IsDrawInstalled())
858 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(
859 pDialogParent
, VclMessageType::Warning
, VclButtonsType::Ok
,
860 SfxResId(STR_REDACTION_NO_DRAW_WARNING
)));
867 DocumentToGraphicRenderer
aRenderer(xSourceDoc
, false);
869 // Get the page margins of the original doc
870 PageMargins aPageMargins
= {-1, -1, -1, -1};
871 if (aRenderer
.isWriter())
872 aPageMargins
= SfxRedactionHelper::getPageMarginsForWriter(xModel
);
873 else if (aRenderer
.isCalc())
874 aPageMargins
= SfxRedactionHelper::getPageMarginsForCalc(xModel
);
876 sal_Int32 nPages
= aRenderer
.getPageCount();
877 std::vector
< GDIMetaFile
> aMetaFiles
;
878 std::vector
< ::Size
> aPageSizes
;
880 // Convert the pages of the document to gdimetafiles
881 SfxRedactionHelper::getPageMetaFilesFromDoc(aMetaFiles
, aPageSizes
, nPages
, aRenderer
);
883 // Create an empty Draw component.
884 uno::Reference
<frame::XDesktop2
> xDesktop
= css::frame::Desktop::create(comphelper::getProcessComponentContext());
885 uno::Reference
<lang::XComponent
> xComponent
= xDesktop
->loadComponentFromURL(u
"private:factory/sdraw"_ustr
, u
"_default"_ustr
, 0, {});
887 if (!xComponent
.is())
889 SAL_WARN("sfx.doc", "SID_REDACTDOC: Failed to load new draw component. loadComponentFromURL returned an empty reference.");
894 // Add the doc pages to the new draw document
895 SfxRedactionHelper::addPagesToDraw(xComponent
, nPages
, aMetaFiles
, aPageSizes
, aPageMargins
, aRedactionTargets
, bIsAutoRedact
);
897 // Show the Redaction toolbar
898 SfxViewFrame
* pViewFrame
= SfxViewFrame::Current();
901 SfxRedactionHelper::showRedactionToolbar(pViewFrame
);
906 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
907 case SID_DIRECTEXPORTDOCASPDF
:
909 uno::Reference
< lang::XComponent
> xComponent( GetCurrentComponent(), uno::UNO_QUERY
);
910 if (!xComponent
.is())
913 uno::Reference
< lang::XServiceInfo
> xServiceInfo( xComponent
, uno::UNO_QUERY
);
915 // Redaction finalization takes place in Draw
916 if ( xServiceInfo
.is() && xServiceInfo
->supportsService(u
"com.sun.star.drawing.DrawingDocument"_ustr
)
917 && SfxRedactionHelper::isRedactMode(rReq
) )
919 OUString
sRedactionStyle(SfxRedactionHelper::getStringParam(rReq
, SID_REDACTION_STYLE
));
921 // Access the draw pages
922 uno::Reference
<drawing::XDrawPagesSupplier
> xDrawPagesSupplier(xComponent
, uno::UNO_QUERY
);
923 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xDrawPagesSupplier
->getDrawPages();
925 sal_Int32 nPageCount
= xDrawPages
->getCount();
926 for (sal_Int32 nPageNum
= 0; nPageNum
< nPageCount
; ++nPageNum
)
929 uno::Reference
< drawing::XDrawPage
> xPage( xDrawPages
->getByIndex( nPageNum
), uno::UNO_QUERY
);
934 // Go through all shapes
935 sal_Int32 nShapeCount
= xPage
->getCount();
936 for (sal_Int32 nShapeNum
= 0; nShapeNum
< nShapeCount
; ++nShapeNum
)
938 uno::Reference
< drawing::XShape
> xCurrShape(xPage
->getByIndex(nShapeNum
), uno::UNO_QUERY
);
939 if (!xCurrShape
.is())
942 uno::Reference
< beans::XPropertySet
> xPropSet(xCurrShape
, uno::UNO_QUERY
);
946 uno::Reference
< beans::XPropertySetInfo
> xInfo
= xPropSet
->getPropertySetInfo();
951 if (xInfo
->hasPropertyByName(u
"Name"_ustr
))
953 uno::Any aAnyShapeName
= xPropSet
->getPropertyValue(u
"Name"_ustr
);
954 aAnyShapeName
>>= sShapeName
;
959 // Rectangle redaction
960 if (sShapeName
== "RectangleRedactionShape"
961 && xInfo
->hasPropertyByName(u
"FillTransparence"_ustr
) && xInfo
->hasPropertyByName(u
"FillColor"_ustr
))
963 xPropSet
->setPropertyValue(u
"FillTransparence"_ustr
, css::uno::Any(static_cast<sal_Int16
>(0)));
964 if (sRedactionStyle
== "White")
966 xPropSet
->setPropertyValue(u
"FillColor"_ustr
, css::uno::Any(COL_WHITE
));
967 xPropSet
->setPropertyValue(u
"LineStyle"_ustr
, css::uno::Any(css::drawing::LineStyle::LineStyle_SOLID
));
968 xPropSet
->setPropertyValue(u
"LineColor"_ustr
, css::uno::Any(COL_BLACK
));
972 xPropSet
->setPropertyValue(u
"FillColor"_ustr
, css::uno::Any(COL_BLACK
));
973 xPropSet
->setPropertyValue(u
"LineStyle"_ustr
, css::uno::Any(css::drawing::LineStyle::LineStyle_NONE
));
976 // Freeform redaction
977 else if (sShapeName
== "FreeformRedactionShape"
978 && xInfo
->hasPropertyByName(u
"LineTransparence"_ustr
) && xInfo
->hasPropertyByName(u
"LineColor"_ustr
))
980 xPropSet
->setPropertyValue(u
"LineTransparence"_ustr
, css::uno::Any(static_cast<sal_Int16
>(0)));
982 if (sRedactionStyle
== "White")
984 xPropSet
->setPropertyValue(u
"LineColor"_ustr
, css::uno::Any(COL_WHITE
));
988 xPropSet
->setPropertyValue(u
"LineColor"_ustr
, css::uno::Any(COL_BLACK
));
996 case SID_EXPORTDOCASPDF
:
999 case SID_EXPORTDOCASEPUB
:
1000 case SID_DIRECTEXPORTDOCASEPUB
:
1003 case SID_SAVEASREMOTE
:
1006 // so far only pdf and epub support Async interface
1007 if (comphelper::LibreOfficeKit::isActive() && rReq
.GetCallMode() == SfxCallMode::ASYNCHRON
1008 && (nId
== SID_EXPORTDOCASEPUB
|| nId
== SID_EXPORTDOCASPDF
))
1011 // derived class may decide to abort this
1012 if( !QuerySlotExecutable( nId
) )
1014 rReq
.SetReturnValue( SfxBoolItem( 0, false ) );
1018 //!! detailed analysis of an error code
1019 SfxObjectShellRef
xLock( this );
1021 // the model can not be closed till the end of this method
1022 // if somebody tries to close it during this time the model will be closed
1023 // at the end of the method
1024 aModelGuard
.Init_Impl( uno::Reference
< util::XCloseable
>( GetModel(), uno::UNO_QUERY
) );
1026 ErrCodeMsg nErrorCode
= ERRCODE_NONE
;
1028 // by default versions should be preserved always except in case of an explicit
1029 // SaveAs via GUI, so the flag must be set accordingly
1030 pImpl
->bPreserveVersions
= (nId
== SID_SAVEDOC
);
1032 // do not save version infos --> (see 'Tools - Options - LibreOffice - Security')
1033 if (SvtSecurityOptions::IsOptionSet(
1034 SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo
) && !SvtSecurityOptions::IsOptionSet(
1035 SvtSecurityOptions::EOption::DocWarnKeepDocVersionInfo
))
1037 pImpl
->bPreserveVersions
= false;
1042 SfxErrorContext
aEc( ERRCTX_SFX_SAVEASDOC
, GetTitle() ); // ???
1044 if ( nId
== SID_SAVEASDOC
|| nId
== SID_SAVEASREMOTE
)
1046 // in case of plugin mode the SaveAs operation means SaveTo
1047 const SfxBoolItem
* pViewOnlyItem
= GetMedium()->GetItemSet().GetItem(SID_VIEWONLY
, false);
1048 if ( pViewOnlyItem
&& pViewOnlyItem
->GetValue() )
1049 rReq
.AppendItem( SfxBoolItem( SID_SAVETO
, true ) );
1052 // TODO/LATER: do the following GUI related actions in standalone method
1054 // Introduce a status indicator for GUI operation
1055 const SfxUnoAnyItem
* pStatusIndicatorItem
= rReq
.GetArg
<SfxUnoAnyItem
>(SID_PROGRESS_STATUSBAR_CONTROL
);
1056 if ( !pStatusIndicatorItem
)
1058 // get statusindicator
1059 uno::Reference
< task::XStatusIndicator
> xStatusIndicator
;
1060 uno::Reference
< frame::XController
> xCtrl( GetModel()->getCurrentController() );
1063 uno::Reference
< task::XStatusIndicatorFactory
> xStatFactory( xCtrl
->getFrame(), uno::UNO_QUERY
);
1064 if( xStatFactory
.is() )
1065 xStatusIndicator
= xStatFactory
->createStatusIndicator();
1068 OSL_ENSURE( xStatusIndicator
.is(), "Can not retrieve default status indicator!" );
1070 if ( xStatusIndicator
.is() )
1072 SfxUnoAnyItem
aStatIndItem( SID_PROGRESS_STATUSBAR_CONTROL
, uno::Any( xStatusIndicator
) );
1074 if ( nId
== SID_SAVEDOC
)
1076 // in case of saving it is not possible to transport the parameters from here
1077 // but it is not clear here whether the saving will be done or saveAs operation
1078 GetMedium()->GetItemSet().Put( aStatIndItem
);
1081 rReq
.AppendItem( aStatIndItem
);
1084 else if ( nId
== SID_SAVEDOC
)
1086 // in case of saving it is not possible to transport the parameters from here
1087 // but it is not clear here whether the saving will be done or saveAs operation
1088 GetMedium()->GetItemSet().Put( *pStatusIndicatorItem
);
1091 // Introduce an interaction handler for GUI operation
1092 const SfxUnoAnyItem
* pInteractionHandlerItem
= rReq
.GetArg
<SfxUnoAnyItem
>(SID_INTERACTIONHANDLER
);
1093 if ( !pInteractionHandlerItem
)
1095 uno::Reference
<css::awt::XWindow
> xParentWindow
;
1096 uno::Reference
<frame::XController
> xCtrl(GetModel()->getCurrentController());
1098 xParentWindow
= xCtrl
->getFrame()->getContainerWindow();
1100 const uno::Reference
< uno::XComponentContext
>& xContext
= ::comphelper::getProcessComponentContext();
1102 uno::Reference
< task::XInteractionHandler2
> xInteract(
1103 task::InteractionHandler::createWithParent(xContext
, xParentWindow
) );
1105 SfxUnoAnyItem
aInteractionItem( SID_INTERACTIONHANDLER
, uno::Any( xInteract
) );
1106 if ( nId
== SID_SAVEDOC
)
1108 // in case of saving it is not possible to transport the parameters from here
1109 // but it is not clear here whether the saving will be done or saveAs operation
1110 GetMedium()->GetItemSet().Put( aInteractionItem
);
1113 rReq
.AppendItem( aInteractionItem
);
1115 else if ( nId
== SID_SAVEDOC
)
1117 // in case of saving it is not possible to transport the parameters from here
1118 // but it is not clear here whether the saving will be done or saveAs operation
1119 GetMedium()->GetItemSet().Put( *pInteractionHandlerItem
);
1123 const SfxStringItem
* pOldPasswordItem
= GetMedium()->GetItemSet().GetItem(SID_PASSWORD
, false);
1124 const SfxUnoAnyItem
* pOldEncryptionDataItem
= GetMedium()->GetItemSet().GetItem(SID_ENCRYPTIONDATA
, false);
1125 const bool bPreselectPassword
1126 = pOldPasswordItem
|| pOldEncryptionDataItem
1127 || (IsLoadReadonly()
1128 && (GetModifyPasswordHash() || GetModifyPasswordInfo().hasElements()));
1130 uno::Sequence
< beans::PropertyValue
> aDispatchArgs
;
1131 if ( rReq
.GetArgs() )
1132 TransformItems( nId
,
1136 bool bForceSaveAs
= nId
== SID_SAVEDOC
&& IsReadOnlyMedium();
1138 if (comphelper::LibreOfficeKit::isActive() && bForceSaveAs
)
1140 // Don't force save as in LOK but report that file cannot be written
1141 // to avoid confusion with exporting for file download purpose
1143 throw task::ErrorCodeIOException(
1144 u
"SfxObjectShell::ExecFile_Impl: ERRCODE_IO_CANTWRITE"_ustr
,
1145 uno::Reference
< uno::XInterface
>(), sal_uInt32(ERRCODE_IO_CANTWRITE
));
1148 const SfxSlot
* pSlot
= GetModule()->GetSlotPool()->GetSlot( bForceSaveAs
? SID_SAVEASDOC
: nId
);
1150 throw uno::Exception(u
"no slot"_ustr
, nullptr);
1152 std::shared_ptr
<SfxStoringHelper
> xHelper
= std::make_shared
<SfxStoringHelper
>();
1153 if (bIsAsync
&& SfxViewShell::Current())
1154 SfxViewShell::Current()->SetStoringHelper(xHelper
);
1156 QueryHiddenInformation(bIsPDFExport
? HiddenWarningFact::WhenCreatingPDF
: HiddenWarningFact::WhenSaving
);
1157 SfxPoolItemHolder aItem
;
1158 if (SID_DIRECTEXPORTDOCASPDF
== nId
)
1159 aItem
= GetSlotState(SID_MAIL_PREPAREEXPORT
);
1160 const SfxBoolItem
* pItem(dynamic_cast<const SfxBoolItem
*>(aItem
.getItem()));
1162 // Fetch value from the pool item early, because GUIStoreModel() can free the pool
1163 // item as part of spinning the main loop if a dialog is opened.
1164 const bool bMailPrepareExport(nullptr != pItem
&& pItem
->GetValue());
1165 if (bMailPrepareExport
)
1167 SfxRequest
aRequest(SID_MAIL_PREPAREEXPORT
, SfxCallMode::SYNCHRON
, GetPool());
1168 aRequest
.AppendItem(SfxBoolItem(FN_NOUPDATE
, true));
1169 ExecuteSlot(aRequest
);
1172 xHelper
->GUIStoreModel( GetModel(),
1173 pSlot
->GetUnoName(),
1176 GetDocumentSignatureState(),
1179 if (bMailPrepareExport
)
1181 SfxRequest
aRequest(SID_MAIL_EXPORT_FINISHED
, SfxCallMode::SYNCHRON
, GetPool());
1182 ExecuteSlot(aRequest
);
1185 // merge aDispatchArgs to the request
1186 SfxAllItemSet
aResultParams( GetPool() );
1187 TransformParameters( nId
,
1190 rReq
.SetArgs( aResultParams
);
1192 // the StoreAsURL/StoreToURL method have called this method with false
1193 // so it has to be restored to true here since it is a call from GUI
1194 GetMedium()->SetUpdatePickList( true );
1196 // TODO: in future it must be done in following way
1197 // if document is opened from GUI, it immediately appears in the picklist
1198 // if the document is a new one then it appears in the picklist immediately
1199 // after SaveAs operation triggered from GUI
1201 catch( const task::ErrorCodeIOException
& aErrorEx
)
1203 TOOLS_WARN_EXCEPTION_IF(ErrCode(aErrorEx
.ErrCode
) != ERRCODE_IO_ABORT
, "sfx.doc", "Fatal IO error during save");
1204 nErrorCode
= { ErrCode(aErrorEx
.ErrCode
), aErrorEx
.Message
};
1206 catch( Exception
& e
)
1208 nErrorCode
= { ERRCODE_IO_GENERAL
, e
.Message
};
1211 // by default versions should be preserved always except in case of an explicit
1212 // SaveAs via GUI, so the flag must be reset to guarantee this
1213 pImpl
->bPreserveVersions
= true;
1214 ErrCodeMsg lErr
=GetErrorCode();
1216 if ( !lErr
&& nErrorCode
)
1219 if ( lErr
&& nErrorCode
== ERRCODE_NONE
)
1221 const SfxBoolItem
* pWarnItem
= rReq
.GetArg
<SfxBoolItem
>(SID_FAIL_ON_WARNING
);
1222 if ( pWarnItem
&& pWarnItem
->GetValue() )
1226 // may be nErrorCode should be shown in future
1227 if ( lErr
!= ERRCODE_IO_ABORT
)
1229 if (comphelper::LibreOfficeKit::isActive())
1230 sendErrorToLOK(lErr
);
1231 else if (!(lErr
== ERRCODE_IO_GENERAL
&& bIsPDFExport
))
1233 SfxErrorContext
aEc(ERRCTX_SFX_SAVEASDOC
,GetTitle());
1234 ErrorHandler::HandleError(lErr
, pDialogParent
);
1238 if (nId
== SID_DIRECTEXPORTDOCASPDF
&&
1239 SfxRedactionHelper::isRedactMode(rReq
))
1241 // Return the finalized redaction shapes back to normal (gray & transparent)
1242 uno::Reference
< lang::XComponent
> xComponent( GetCurrentComponent(), uno::UNO_QUERY
);
1243 if (!xComponent
.is())
1246 uno::Reference
< lang::XServiceInfo
> xServiceInfo( xComponent
, uno::UNO_QUERY
);
1248 // Redaction finalization takes place in Draw
1249 if ( xServiceInfo
.is() && xServiceInfo
->supportsService(u
"com.sun.star.drawing.DrawingDocument"_ustr
) )
1251 // Access the draw pages
1252 uno::Reference
<drawing::XDrawPagesSupplier
> xDrawPagesSupplier(xComponent
, uno::UNO_QUERY
);
1253 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xDrawPagesSupplier
->getDrawPages();
1255 sal_Int32 nPageCount
= xDrawPages
->getCount();
1256 for (sal_Int32 nPageNum
= 0; nPageNum
< nPageCount
; ++nPageNum
)
1259 uno::Reference
< drawing::XDrawPage
> xPage( xDrawPages
->getByIndex( nPageNum
), uno::UNO_QUERY
);
1264 // Go through all shapes
1265 sal_Int32 nShapeCount
= xPage
->getCount();
1266 for (sal_Int32 nShapeNum
= 0; nShapeNum
< nShapeCount
; ++nShapeNum
)
1268 uno::Reference
< drawing::XShape
> xCurrShape(xPage
->getByIndex(nShapeNum
), uno::UNO_QUERY
);
1269 if (!xCurrShape
.is())
1272 uno::Reference
< beans::XPropertySet
> xPropSet(xCurrShape
, uno::UNO_QUERY
);
1276 uno::Reference
< beans::XPropertySetInfo
> xInfo
= xPropSet
->getPropertySetInfo();
1280 // Not a shape we converted?
1281 if (!xInfo
->hasPropertyByName(u
"Name"_ustr
))
1284 OUString sShapeName
;
1285 if (xInfo
->hasPropertyByName(u
"Name"_ustr
))
1287 uno::Any aAnyShapeName
= xPropSet
->getPropertyValue(u
"Name"_ustr
);
1288 aAnyShapeName
>>= sShapeName
;
1293 // Rectangle redaction
1294 if (sShapeName
== "RectangleRedactionShape"
1295 && xInfo
->hasPropertyByName(u
"FillTransparence"_ustr
) && xInfo
->hasPropertyByName(u
"FillColor"_ustr
))
1297 xPropSet
->setPropertyValue(u
"FillTransparence"_ustr
, css::uno::Any(static_cast<sal_Int16
>(50)));
1298 xPropSet
->setPropertyValue(u
"FillColor"_ustr
, css::uno::Any(COL_GRAY7
));
1299 xPropSet
->setPropertyValue(u
"LineStyle"_ustr
, css::uno::Any(css::drawing::LineStyle::LineStyle_NONE
));
1302 // Freeform redaction
1303 else if (sShapeName
== "FreeformRedactionShape")
1305 xPropSet
->setPropertyValue(u
"LineTransparence"_ustr
, css::uno::Any(static_cast<sal_Int16
>(50)));
1306 xPropSet
->setPropertyValue(u
"LineColor"_ustr
, css::uno::Any(COL_GRAY7
));
1315 if ( nId
== SID_EXPORTDOCASPDF
)
1317 // This function is used by the SendMail function that needs information if an export
1318 // file was written or not. This could be due to cancellation of the export
1319 // or due to an error. So IO abort must be handled like an error!
1320 nErrorCode
= ( lErr
!= ERRCODE_IO_ABORT
) && ( nErrorCode
== ERRCODE_NONE
) ? nErrorCode
: lErr
;
1323 if ( ( nId
== SID_SAVEASDOC
|| nId
== SID_SAVEASREMOTE
) && nErrorCode
== ERRCODE_NONE
)
1325 const SfxBoolItem
* saveTo
= rReq
.GetArg
<SfxBoolItem
>(SID_SAVETO
);
1326 if (saveTo
== nullptr || !saveTo
->GetValue())
1328 if (SfxViewFrame
* pFrame
= GetFrame())
1329 pFrame
->RemoveInfoBar(u
"readonly");
1330 SetReadOnlyUI(false);
1334 if (nId
== SID_SAVEDOC
&& bRememberSignature
&& rSignatureInfosRemembered
.hasElements())
1335 ResignDocument(rSignatureInfosRemembered
);
1337 rReq
.SetReturnValue( SfxBoolItem(0, nErrorCode
== ERRCODE_NONE
) );
1347 SfxAllItemSet
aArgs( GetPool() );
1348 aArgs
.Put( SfxBoolItem( SID_SAVEACOPYITEM
, true ) );
1349 SfxRequest
aSaveACopyReq( SID_EXPORTDOC
, SfxCallMode::API
, aArgs
);
1350 ExecFile_Impl( aSaveACopyReq
);
1351 if ( !aSaveACopyReq
.IsDone() )
1359 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1363 // Evaluate Parameter
1364 const SfxBoolItem
* pSaveItem
= rReq
.GetArg
<SfxBoolItem
>(SID_CLOSEDOC_SAVE
);
1365 const SfxStringItem
* pNameItem
= rReq
.GetArg
<SfxStringItem
>(SID_CLOSEDOC_FILENAME
);
1368 if ( pSaveItem
->GetValue() )
1372 #if HAVE_FEATURE_SCRIPTING
1373 SbxBase::SetError( ERRCODE_BASIC_WRONG_ARGS
);
1378 SfxAllItemSet
aArgs( GetPool() );
1379 SfxStringItem
aTmpItem( SID_FILE_NAME
, pNameItem
->GetValue() );
1380 aArgs
.Put( aTmpItem
);
1381 SfxRequest
aSaveAsReq( SID_SAVEASDOC
, SfxCallMode::API
, aArgs
);
1382 ExecFile_Impl( aSaveAsReq
);
1383 if ( !aSaveAsReq
.IsDone() )
1393 // Cancelled by the user?
1394 if (!PrepareClose())
1396 rReq
.SetReturnValue( SfxBoolItem(0, false) );
1401 SetModified( false );
1402 ErrCodeMsg lErr
= GetErrorCode();
1404 if (comphelper::LibreOfficeKit::isActive())
1405 sendErrorToLOK(lErr
);
1407 ErrorHandler::HandleError(lErr
, pDialogParent
);
1409 rReq
.SetReturnValue( SfxBoolItem(0, true) );
1411 rReq
.ReleaseArgs(); // because the pool is destroyed in Close
1416 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1417 case SID_DOCTEMPLATE
:
1419 // save as document templates
1420 SfxSaveAsTemplateDialog
aDlg(pDialogParent
, GetModel());
1430 case SID_CANCELCHECKOUT
:
1432 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
1433 VclMessageType::Question
, VclButtonsType::YesNo
, SfxResId(STR_QUERY_CANCELCHECKOUT
)));
1434 if (xBox
->run() == RET_YES
)
1438 // Reload the document as we may still have local changes
1439 if (SfxViewFrame
* pFrame
= GetFrame())
1440 pFrame
->GetDispatcher()->Execute(SID_RELOAD
);
1451 // Prevent entry in the Pick-lists
1453 GetMedium()->SetUpdatePickList( false );
1455 // Ignore()-branches have already returned
1460 void SfxObjectShell::GetState_Impl(SfxItemSet
&rSet
)
1462 SfxWhichIter
aIter( rSet
);
1464 for ( sal_uInt16 nWhich
= aIter
.FirstWhich(); nWhich
; nWhich
= aIter
.NextWhich() )
1471 Reference
< XCmisDocument
> xCmisDoc( GetModel(), uno::UNO_QUERY
);
1472 const uno::Sequence
< document::CmisProperty
> aCmisProperties
= xCmisDoc
->getCmisProperties();
1474 if ( xCmisDoc
->isVersionable( ) && aCmisProperties
.hasElements( ) )
1476 // Loop over the CMIS Properties to find cmis:isVersionSeriesCheckedOut
1477 bool bIsGoogleFile
= false;
1478 bool bCheckedOut
= false;
1479 for ( const auto& rCmisProperty
: aCmisProperties
)
1481 if ( rCmisProperty
.Id
== "cmis:isVersionSeriesCheckedOut" )
1483 uno::Sequence
< sal_Bool
> bTmp
;
1484 rCmisProperty
.Value
>>= bTmp
;
1485 bCheckedOut
= bTmp
[0];
1487 // using title to know if it's a Google Drive file
1488 // maybe there's a safer way.
1489 if ( rCmisProperty
.Name
== "title" )
1490 bIsGoogleFile
= true;
1492 bShow
= !bCheckedOut
&& !bIsGoogleFile
;
1497 rSet
.DisableItem( nWhich
);
1498 rSet
.Put( SfxVisibilityItem( nWhich
, false ) );
1503 case SID_CANCELCHECKOUT
:
1507 Reference
< XCmisDocument
> xCmisDoc( GetModel(), uno::UNO_QUERY
);
1508 const uno::Sequence
< document::CmisProperty
> aCmisProperties
= xCmisDoc
->getCmisProperties( );
1510 if ( xCmisDoc
->isVersionable( ) && aCmisProperties
.hasElements( ) )
1512 // Loop over the CMIS Properties to find cmis:isVersionSeriesCheckedOut
1513 bool bCheckedOut
= false;
1514 auto pProp
= std::find_if(aCmisProperties
.begin(), aCmisProperties
.end(),
1515 [](const document::CmisProperty
& rProp
) { return rProp
.Id
== "cmis:isVersionSeriesCheckedOut"; });
1516 if (pProp
!= aCmisProperties
.end())
1518 uno::Sequence
< sal_Bool
> bTmp
;
1519 pProp
->Value
>>= bTmp
;
1520 bCheckedOut
= bTmp
[0];
1522 bShow
= bCheckedOut
;
1527 rSet
.DisableItem( nWhich
);
1528 rSet
.Put( SfxVisibilityItem( nWhich
, false ) );
1535 SfxObjectShell
*pDoc
= this;
1536 SfxViewFrame
* pFrame
= GetFrame();
1538 pFrame
= SfxViewFrame::GetFirst( this );
1540 if ( !pFrame
|| !pDoc
->HasName() ||
1541 !IsOwnStorageFormat( *pDoc
->GetMedium() ) )
1542 rSet
.DisableItem( nWhich
);
1547 if ( IsReadOnly() || isSaveLocked())
1549 rSet
.DisableItem(nWhich
);
1552 rSet
.Put(SfxStringItem(nWhich
, SfxResId(STR_SAVEDOC
)));
1561 rSet
.Put(SfxStringItem(nWhich
, SfxResId(STR_CLOSEDOC
)));
1567 if (!(pImpl
->nLoadedFlags
& SfxLoadedFlags::MAINDOCUMENT
)
1568 || isExportLocked())
1570 rSet
.DisableItem( nWhich
);
1573 if ( /*!pCombinedFilters ||*/ !GetMedium() )
1574 rSet
.DisableItem( nWhich
);
1576 rSet
.Put( SfxStringItem( nWhich
, SfxResId(STR_SAVEASDOC
) ) );
1582 if (!(pImpl
->nLoadedFlags
& SfxLoadedFlags::MAINDOCUMENT
) || isExportLocked())
1584 rSet
.DisableItem( nWhich
);
1587 if ( /*!pCombinedFilters ||*/ !GetMedium() )
1588 rSet
.DisableItem( nWhich
);
1590 rSet
.Put( SfxStringItem( nWhich
, SfxResId(STR_SAVEACOPY
) ) );
1594 case SID_DOCTEMPLATE
:
1596 case SID_EXPORTDOCASPDF
:
1597 case SID_DIRECTEXPORTDOCASPDF
:
1598 case SID_EXPORTDOCASEPUB
:
1599 case SID_DIRECTEXPORTDOCASEPUB
:
1601 case SID_AUTOREDACTDOC
:
1602 case SID_SAVEASREMOTE
:
1604 if (isExportLocked())
1605 rSet
.DisableItem( nWhich
);
1609 case SID_DOC_MODIFIED
:
1611 rSet
.Put( SfxBoolItem( SID_DOC_MODIFIED
, IsModified() ) );
1617 rSet
.Put( SfxBoolItem( SID_MODIFIED
, IsModified() ) );
1621 case SID_DOCINFO_TITLE
:
1623 rSet
.Put( SfxStringItem(
1624 SID_DOCINFO_TITLE
, getDocProperties()->getTitle() ) );
1629 if( GetMedium() && HasName() )
1630 rSet
.Put( SfxStringItem(
1631 SID_FILE_NAME
, GetMedium()->GetName() ) );
1636 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst(this);
1639 SignatureState eState
= GetDocumentSignatureState();
1640 InfobarType
aInfobarType(InfobarType::INFO
);
1641 OUString
sMessage(u
""_ustr
);
1645 case SignatureState::BROKEN
:
1646 sMessage
= SfxResId(STR_SIGNATURE_BROKEN
);
1647 aInfobarType
= InfobarType::DANGER
;
1649 case SignatureState::INVALID
:
1650 // If we are remembering the certificates, it should be kept as valid
1651 sMessage
= SfxResId(bRememberSignature
? STR_SIGNATURE_OK
: STR_SIGNATURE_INVALID
);
1652 // Warning only, I've tried Danger and it looked too scary
1653 aInfobarType
= ( bRememberSignature
? InfobarType::INFO
: InfobarType::WARNING
);
1655 case SignatureState::NOTVALIDATED
:
1656 sMessage
= SfxResId(STR_SIGNATURE_NOTVALIDATED
);
1657 aInfobarType
= InfobarType::WARNING
;
1659 case SignatureState::PARTIAL_OK
:
1660 sMessage
= SfxResId(STR_SIGNATURE_PARTIAL_OK
);
1661 aInfobarType
= InfobarType::WARNING
;
1663 case SignatureState::OK
:
1664 sMessage
= SfxResId(STR_SIGNATURE_OK
);
1665 aInfobarType
= InfobarType::INFO
;
1667 case SignatureState::NOTVALIDATED_PARTIAL_OK
:
1668 sMessage
= SfxResId(STR_SIGNATURE_NOTVALIDATED_PARTIAL_OK
);
1669 aInfobarType
= InfobarType::WARNING
;
1671 //FIXME SignatureState::Unknown, own message?
1677 if ( !pFrame
->HasInfoBarWithID(u
"signature") )
1679 if ( !sMessage
.isEmpty() )
1681 auto pInfoBar
= pFrame
->AppendInfoBar(u
"signature"_ustr
, u
""_ustr
, sMessage
, aInfobarType
);
1682 if (pInfoBar
== nullptr || pInfoBar
->isDisposed())
1684 weld::Button
& rBtn
= pInfoBar
->addButton();
1685 rBtn
.set_label(SfxResId(STR_SIGNATURE_SHOW
));
1686 rBtn
.connect_clicked(LINK(this, SfxObjectShell
, SignDocumentHandler
));
1689 else // info bar exists already
1691 if ( eState
== SignatureState::NOSIGNATURES
)
1692 pFrame
->RemoveInfoBar(u
"signature");
1694 pFrame
->UpdateInfoBar(u
"signature", u
""_ustr
, sMessage
, aInfobarType
);
1698 rSet
.Put( SfxUInt16Item( SID_SIGNATURE
, static_cast<sal_uInt16
>(GetDocumentSignatureState()) ) );
1701 case SID_MACRO_SIGNATURE
:
1703 // the slot makes sense only if there is a macro in the document
1704 if ( pImpl
->documentStorageHasMacros() || pImpl
->aMacroMode
.hasMacroLibrary() )
1705 rSet
.Put( SfxUInt16Item( SID_MACRO_SIGNATURE
, static_cast<sal_uInt16
>(GetScriptingSignatureState()) ) );
1707 rSet
.DisableItem( nWhich
);
1710 case SID_DOC_REPAIR
:
1712 SfxUndoManager
* pIUndoMgr
= GetUndoManager();
1714 rSet
.Put( SfxBoolItem(nWhich
, pIUndoMgr
->IsEmptyActions()) );
1716 rSet
.DisableItem( nWhich
);
1723 IMPL_LINK_NOARG(SfxObjectShell
, SignDocumentHandler
, weld::Button
&, void)
1725 SfxViewFrame
* pViewFrm
= SfxViewFrame::GetFirst(this);
1728 SAL_WARN("sfx.appl", "There should be some SfxViewFrame associated here");
1731 SfxUnoFrameItem
aDocFrame(SID_FILLFRAME
, pViewFrm
->GetFrame().GetFrameInterface());
1732 pViewFrm
->GetDispatcher()->ExecuteList(SID_SIGNATURE
, SfxCallMode::SLOT
, {}, { &aDocFrame
});
1735 void SfxObjectShell::ExecProps_Impl(SfxRequest
&rReq
)
1737 switch ( rReq
.GetSlot() )
1741 SetModified( rReq
.GetArgs()->Get(SID_MODIFIED
).GetValue() );
1747 SetTitle( rReq
.GetArgs()->Get(SID_DOCTITLE
).GetValue() );
1751 case SID_DOCINFO_AUTHOR
:
1752 getDocProperties()->setAuthor( static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(rReq
.GetSlot())).GetValue() );
1755 case SID_DOCINFO_COMMENTS
:
1756 getDocProperties()->setDescription( static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(rReq
.GetSlot())).GetValue() );
1759 case SID_DOCINFO_KEYWORDS
:
1761 const OUString aStr
= static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(rReq
.GetSlot())).GetValue();
1762 getDocProperties()->setKeywords(
1763 ::comphelper::string::convertCommaSeparated(aStr
) );
1770 void SfxObjectShell::StateProps_Impl(SfxItemSet
&rSet
)
1772 SfxWhichIter
aIter(rSet
);
1773 for ( sal_uInt16 nSID
= aIter
.FirstWhich(); nSID
; nSID
= aIter
.NextWhich() )
1777 case SID_DOCINFO_AUTHOR
:
1779 rSet
.Put( SfxStringItem( nSID
,
1780 getDocProperties()->getAuthor() ) );
1784 case SID_DOCINFO_COMMENTS
:
1786 rSet
.Put( SfxStringItem( nSID
,
1787 getDocProperties()->getDescription()) );
1791 case SID_DOCINFO_KEYWORDS
:
1793 rSet
.Put( SfxStringItem( nSID
, ::comphelper::string::
1794 convertCommaSeparated(getDocProperties()->getKeywords())) );
1800 OSL_FAIL( "Not supported anymore!" );
1804 case SID_DOCFULLNAME
:
1806 rSet
.Put( SfxStringItem( SID_DOCFULLNAME
, GetTitle(SFX_TITLE_FULLNAME
) ) );
1812 rSet
.Put( SfxStringItem( SID_DOCTITLE
, GetTitle() ) );
1816 case SID_DOC_READONLY
:
1818 rSet
.Put( SfxBoolItem( SID_DOC_READONLY
, IsReadOnly() ) );
1824 rSet
.Put( SfxBoolItem( SID_DOC_SAVED
, !IsModified() ) );
1830 rSet
.Put( SfxBoolItem( SID_CLOSING
, false ) );
1834 case SID_DOC_LOADING
:
1835 rSet
.Put( SfxBoolItem( nSID
, ! ( pImpl
->nLoadedFlags
& SfxLoadedFlags::MAINDOCUMENT
) ) );
1838 case SID_IMG_LOADING
:
1839 rSet
.Put( SfxBoolItem( nSID
, ! ( pImpl
->nLoadedFlags
& SfxLoadedFlags::IMAGES
) ) );
1846 void SfxObjectShell::ExecView_Impl(SfxRequest
&rReq
)
1848 switch ( rReq
.GetSlot() )
1852 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst( this );
1854 pFrame
->GetFrame().Appear();
1855 rReq
.SetReturnValue( SfxObjectItem( 0, pFrame
) );
1863 void SfxObjectShell::StateView_Impl(SfxItemSet
& /*rSet*/)
1867 /// Does this ZIP storage have a signature stream?
1868 static bool HasSignatureStream(const uno::Reference
<embed::XStorage
>& xStorage
)
1873 if (xStorage
->hasByName(u
"META-INF"_ustr
))
1878 uno::Reference
<embed::XStorage
> xMetaInf
1879 = xStorage
->openStorageElement(u
"META-INF"_ustr
, embed::ElementModes::READ
);
1882 return xMetaInf
->hasByName(u
"documentsignatures.xml"_ustr
)
1883 || xMetaInf
->hasByName(u
"macrosignatures.xml"_ustr
)
1884 || xMetaInf
->hasByName(u
"packagesignatures.xml"_ustr
);
1887 catch (const css::io::IOException
&)
1889 TOOLS_WARN_EXCEPTION("sfx.doc", "HasSignatureStream: failed to open META-INF");
1894 return xStorage
->hasByName(u
"_xmlsignatures"_ustr
);
1897 uno::Sequence
< security::DocumentSignatureInformation
> SfxObjectShell::GetDocumentSignatureInformation( bool bScriptingContent
, const uno::Reference
< security::XDocumentDigitalSignatures
>& xSigner
)
1899 uno::Sequence
< security::DocumentSignatureInformation
> aResult
;
1900 uno::Reference
< security::XDocumentDigitalSignatures
> xLocSigner
= xSigner
;
1902 bool bSupportsSigning
= GetMedium() && GetMedium()->GetFilter() && GetMedium()->GetFilter()->GetSupportsSigning();
1903 if (GetMedium() && !GetMedium()->GetName().isEmpty() && ((IsOwnStorageFormat(*GetMedium()) && GetMedium()->GetStorage().is()) || bSupportsSigning
))
1907 if ( !xLocSigner
.is() )
1912 uno::Reference
< beans::XPropertySet
> xPropSet( GetStorage(), uno::UNO_QUERY
);
1914 xPropSet
->getPropertyValue(u
"Version"_ustr
) >>= aVersion
;
1916 catch( uno::Exception
& )
1920 xLocSigner
.set( security::DocumentDigitalSignatures::createWithVersion(comphelper::getProcessComponentContext(), aVersion
) );
1924 if ( bScriptingContent
)
1926 aResult
= xLocSigner
->verifyScriptingContentSignatures(
1927 GetMedium()->GetScriptingStorageToSign_Impl(),
1928 uno::Reference
<io::XInputStream
>());
1932 if (GetMedium()->GetStorage(false).is())
1934 // Something ZIP-based.
1935 // Only call into xmlsecurity if we see a signature stream,
1936 // as libxmlsec init is expensive.
1937 if (HasSignatureStream(GetMedium()->GetZipStorageToSign_Impl()))
1938 aResult
= xLocSigner
->verifyDocumentContentSignatures( GetMedium()->GetZipStorageToSign_Impl(),
1939 uno::Reference
< io::XInputStream
>() );
1943 // Not ZIP-based, e.g. PDF.
1945 // Create temp file if needed.
1946 GetMedium()->CreateTempFile(/*bReplace=*/false);
1948 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(GetMedium()->GetName(), StreamMode::READ
));
1949 uno::Reference
<io::XStream
> xStream(new utl::OStreamWrapper(*pStream
));
1950 uno::Reference
<io::XInputStream
> xInputStream(xStream
, uno::UNO_QUERY
);
1951 aResult
= xLocSigner
->verifyDocumentContentSignatures(uno::Reference
<embed::XStorage
>(), xInputStream
);
1955 catch( css::uno::Exception
& )
1957 TOOLS_WARN_EXCEPTION("sfx.doc", "Failed to get document signature information");
1964 void SfxObjectShell::SetRememberCurrentSignature(bool bRemember
)
1968 rSignatureInfosRemembered
= GetDocumentSignatureInformation(false);
1969 bRememberSignature
= true;
1973 rSignatureInfosRemembered
= uno::Sequence
<security::DocumentSignatureInformation
>();
1974 bRememberSignature
= false;
1978 SignatureState
SfxObjectShell::ImplGetSignatureState( bool bScriptingContent
)
1980 SignatureState
* pState
= bScriptingContent
? &pImpl
->nScriptingSignatureState
: &pImpl
->nDocumentSignatureState
;
1982 if ( *pState
== SignatureState::UNKNOWN
)
1984 *pState
= SignatureState::NOSIGNATURES
;
1986 uno::Sequence
< security::DocumentSignatureInformation
> aInfos
= GetDocumentSignatureInformation( bScriptingContent
);
1987 *pState
= DocumentSignatures::getSignatureState(aInfos
);
1989 // repaired package cannot be trusted
1990 if (*pState
!= SignatureState::NOSIGNATURES
1991 && GetMedium()->IsRepairPackage())
1993 *pState
= SignatureState::BROKEN
;
1997 if ( *pState
== SignatureState::OK
|| *pState
== SignatureState::NOTVALIDATED
1998 || *pState
== SignatureState::PARTIAL_OK
)
2001 *pState
= SignatureState::INVALID
;
2007 bool SfxObjectShell::PrepareForSigning(weld::Window
* pDialogParent
)
2009 // check whether the document is signed
2010 ImplGetSignatureState(); // document signature
2011 if (GetMedium() && GetMedium()->GetFilter() && GetMedium()->GetFilter()->IsOwnFormat())
2012 ImplGetSignatureState( true ); // script signature
2013 bool bHasSign
= ( pImpl
->nScriptingSignatureState
!= SignatureState::NOSIGNATURES
|| pImpl
->nDocumentSignatureState
!= SignatureState::NOSIGNATURES
);
2015 // the target ODF version on saving (only valid when signing ODF of course)
2016 SvtSaveOptions::ODFSaneDefaultVersion nVersion
= GetODFSaneDefaultVersion();
2018 // the document is not new and is not modified
2019 OUString
aODFVersion(comphelper::OStorageHelper::GetODFVersionFromStorage(GetStorage()));
2021 if ( IsModified() || !GetMedium() || GetMedium()->GetName().isEmpty()
2022 || (GetMedium()->GetFilter()->IsOwnFormat() && aODFVersion
.compareTo(ODFVER_012_TEXT
) < 0 && !bHasSign
))
2024 // the document might need saving ( new, modified or in ODF1.1 format without signature )
2026 if (nVersion
>= SvtSaveOptions::ODFSVER_012
)
2028 OUString
sQuestion(bHasSign
? SfxResId(STR_XMLSEC_QUERY_SAVESIGNEDBEFORESIGN
) : SfxResId(RID_SVXSTR_XMLSEC_QUERY_SAVEBEFORESIGN
));
2029 std::unique_ptr
<weld::MessageDialog
> xQuestion
;
2031 if (!bRememberSignature
)
2033 xQuestion
= std::unique_ptr
<weld::MessageDialog
>(Application::CreateMessageDialog(pDialogParent
,
2034 VclMessageType::Question
, VclButtonsType::YesNo
, sQuestion
));
2037 if ( bRememberSignature
|| ( xQuestion
!= nullptr && xQuestion
->run() == RET_YES
) )
2039 sal_uInt16 nId
= SID_SAVEDOC
;
2040 if ( !GetMedium() || GetMedium()->GetName().isEmpty() )
2041 nId
= SID_SAVEASDOC
;
2042 SfxRequest
aSaveRequest( nId
, SfxCallMode::SLOT
, GetPool() );
2043 //ToDo: Review. We needed to call SetModified, otherwise the document would not be saved.
2045 ExecFile_Impl( aSaveRequest
);
2047 // Check if it is stored a format which supports signing
2048 if (GetMedium() && GetMedium()->GetFilter() && !GetMedium()->GetName().isEmpty()
2049 && ((!GetMedium()->GetFilter()->IsOwnFormat()
2050 && !GetMedium()->GetFilter()->GetSupportsSigning())
2051 || (GetMedium()->GetFilter()->IsOwnFormat()
2052 && !GetMedium()->HasStorage_Impl())))
2054 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(
2055 pDialogParent
, VclMessageType::Info
, VclButtonsType::Ok
,
2056 SfxResId(STR_INFO_WRONGDOCFORMAT
)));
2064 // When the document is modified then we must not show the
2065 // digital signatures dialog
2066 // If we have come here then the user denied to save.
2073 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(pDialogParent
,
2074 VclMessageType::Warning
, VclButtonsType::Ok
, SfxResId(STR_XMLSEC_ODF12_EXPECTED
)));
2079 if ( IsModified() || !GetMedium() || GetMedium()->GetName().isEmpty() )
2083 // the document is not modified currently, so it can not become modified after signing
2084 pImpl
->m_bAllowModifiedBackAfterSigning
= false;
2085 if ( IsEnableSetModified() || /*bRememberSignature == */true )
2087 EnableSetModified( false );
2088 pImpl
->m_bAllowModifiedBackAfterSigning
= true;
2091 // we have to store to the original document, the original medium should be closed for this time
2092 if ( ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
2094 GetMedium()->CloseAndRelease();
2100 void SfxObjectShell::RecheckSignature(bool bAlsoRecheckScriptingSignature
)
2102 if (bAlsoRecheckScriptingSignature
)
2103 pImpl
->nScriptingSignatureState
= SignatureState::UNKNOWN
; // Re-Check
2105 pImpl
->nDocumentSignatureState
= SignatureState::UNKNOWN
; // Re-Check
2107 Invalidate(SID_SIGNATURE
);
2108 Invalidate(SID_MACRO_SIGNATURE
);
2109 Broadcast(SfxHint(SfxHintId::TitleChanged
));
2112 void SfxObjectShell::AfterSigning(bool bSignSuccess
, bool bSignScriptingContent
)
2114 pImpl
->m_bSavingForSigning
= true;
2115 DoSaveCompleted( GetMedium() );
2116 pImpl
->m_bSavingForSigning
= false;
2119 RecheckSignature(bSignScriptingContent
);
2121 if ( pImpl
->m_bAllowModifiedBackAfterSigning
|| /* bRememberSignature ==*/ true )
2122 EnableSetModified();
2125 bool SfxObjectShell::CheckIsReadonly(bool bSignScriptingContent
, weld::Window
* pDialogParent
)
2127 if (GetMedium()->IsOriginallyReadOnly())
2129 // If the file is physically read-only, we just show the existing signatures
2132 OUString
aODFVersion(
2133 comphelper::OStorageHelper::GetODFVersionFromStorage(GetStorage()));
2134 uno::Reference
<security::XDocumentDigitalSignatures
> xSigner(
2135 security::DocumentDigitalSignatures::createWithVersionAndValidSignature(
2136 comphelper::getProcessComponentContext(), aODFVersion
, HasValidSignatures()));
2139 xSigner
->setParentWindow(pDialogParent
->GetXWindow());
2141 if (bSignScriptingContent
)
2142 xSigner
->showScriptingContentSignatures(GetMedium()->GetScriptingStorageToSign_Impl(),
2143 uno::Reference
<io::XInputStream
>());
2146 uno::Reference
<embed::XStorage
> xStorage
= GetMedium()->GetZipStorageToSign_Impl();
2148 xSigner
->showDocumentContentSignatures(xStorage
,
2149 uno::Reference
<io::XInputStream
>());
2152 std::unique_ptr
<SvStream
> pStream(
2153 utl::UcbStreamHelper::CreateStream(GetName(), StreamMode::READ
));
2157 pStream
= utl::UcbStreamHelper::CreateStream(GetMedium()->GetName(), StreamMode::READ
);
2161 SAL_WARN( "sfx.doc", "Couldn't use signing functionality!" );
2166 uno::Reference
<io::XInputStream
> xStream(new utl::OStreamWrapper(*pStream
));
2167 xSigner
->showDocumentContentSignatures(uno::Reference
<embed::XStorage
>(),
2172 catch (const uno::Exception
&)
2174 SAL_WARN("sfx.doc", "Couldn't use signing functionality!");
2181 bool SfxObjectShell::HasValidSignatures() const
2183 return pImpl
->nDocumentSignatureState
== SignatureState::OK
2184 || pImpl
->nDocumentSignatureState
== SignatureState::NOTVALIDATED
2185 || pImpl
->nDocumentSignatureState
== SignatureState::PARTIAL_OK
;
2188 SignatureState
SfxObjectShell::GetDocumentSignatureState()
2190 return ImplGetSignatureState();
2193 void SfxObjectShell::SignDocumentContent(weld::Window
* pDialogParent
, const std::function
<void(bool)>& rCallback
)
2195 if (!PrepareForSigning(pDialogParent
))
2201 if (CheckIsReadonly(false, pDialogParent
))
2207 SfxViewFrame
* pFrame
= GetFrame();
2208 SfxViewShell
* pViewShell
= pFrame
? pFrame
->GetViewShell() : nullptr;
2209 // Async, all code before the end has to go into the callback.
2210 GetMedium()->SignContents_Impl(pDialogParent
, false, HasValidSignatures(), pViewShell
, [this, rCallback
](bool bSignSuccess
) {
2211 AfterSigning(bSignSuccess
, false);
2213 rCallback(bSignSuccess
);
2217 bool SfxObjectShell::ResignDocument(uno::Sequence
< security::DocumentSignatureInformation
>& rSignaturesInfo
)
2219 bool bSignSuccess
= true;
2221 // This should be at most one element, automatic iteration to avoid pointing issues in case no signs
2222 for (auto & rInfo
: rSignaturesInfo
)
2224 auto xCert
= rInfo
.Signer
;
2227 svl::crypto::SigningContext aSigningContext
;
2228 aSigningContext
.m_xCertificate
= std::move(xCert
);
2229 bSignSuccess
&= SignDocumentContentUsingCertificate(aSigningContext
);
2233 return bSignSuccess
;
2236 bool SfxObjectShell::SignDocumentContentUsingCertificate(svl::crypto::SigningContext
& rSigningContext
)
2238 // 1. PrepareForSigning
2240 // check whether the document is signed
2241 ImplGetSignatureState(false); // document signature
2242 if (GetMedium() && GetMedium()->GetFilter() && GetMedium()->GetFilter()->IsOwnFormat())
2243 ImplGetSignatureState( true ); // script signature
2244 bool bHasSign
= ( pImpl
->nScriptingSignatureState
!= SignatureState::NOSIGNATURES
|| pImpl
->nDocumentSignatureState
!= SignatureState::NOSIGNATURES
);
2246 // the target ODF version on saving (only valid when signing ODF of course)
2247 SvtSaveOptions::ODFSaneDefaultVersion nVersion
= GetODFSaneDefaultVersion();
2249 // the document is not new and is not modified
2250 OUString
aODFVersion(comphelper::OStorageHelper::GetODFVersionFromStorage(GetStorage()));
2252 if (IsModified() || !GetMedium() || GetMedium()->GetName().isEmpty()
2253 || (GetMedium()->GetFilter()->IsOwnFormat() && aODFVersion
.compareTo(ODFVER_012_TEXT
) < 0 && !bHasSign
))
2255 if (nVersion
>= SvtSaveOptions::ODFSVER_012
)
2257 sal_uInt16 nId
= SID_SAVEDOC
;
2258 if ( !GetMedium() || GetMedium()->GetName().isEmpty() )
2259 nId
= SID_SAVEASDOC
;
2260 SfxRequest
aSaveRequest( nId
, SfxCallMode::SLOT
, GetPool() );
2261 //ToDo: Review. We needed to call SetModified, otherwise the document would not be saved.
2263 ExecFile_Impl( aSaveRequest
);
2265 // Check if it is stored a format which supports signing
2266 if (GetMedium() && GetMedium()->GetFilter() && !GetMedium()->GetName().isEmpty()
2267 && ((!GetMedium()->GetFilter()->IsOwnFormat()
2268 && !GetMedium()->GetFilter()->GetSupportsSigning())
2269 || (GetMedium()->GetFilter()->IsOwnFormat()
2270 && !GetMedium()->HasStorage_Impl())))
2280 if ( IsModified() || !GetMedium() || GetMedium()->GetName().isEmpty() )
2284 // the document is not modified currently, so it can not become modified after signing
2285 pImpl
->m_bAllowModifiedBackAfterSigning
= false;
2286 if ( IsEnableSetModified() )
2288 EnableSetModified( false );
2289 pImpl
->m_bAllowModifiedBackAfterSigning
= true;
2292 // we have to store to the original document, the original medium should be closed for this time
2293 bool bResult
= ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
);
2298 GetMedium()->CloseAndRelease();
2300 // 2. Check Read-Only
2301 if (GetMedium()->IsOriginallyReadOnly())
2305 bool bSignSuccess
= GetMedium()->SignDocumentContentUsingCertificate(
2306 GetBaseModel(), HasValidSignatures(), rSigningContext
);
2309 AfterSigning(bSignSuccess
, false);
2314 void SfxObjectShell::SignSignatureLine(weld::Window
* pDialogParent
,
2315 const OUString
& aSignatureLineId
,
2316 const Reference
<XCertificate
>& xCert
,
2317 const Reference
<XGraphic
>& xValidGraphic
,
2318 const Reference
<XGraphic
>& xInvalidGraphic
,
2319 const OUString
& aComment
)
2321 if (!PrepareForSigning(pDialogParent
))
2324 if (CheckIsReadonly(false, pDialogParent
))
2327 SfxViewFrame
* pFrame
= GetFrame();
2328 SfxViewShell
* pViewShell
= pFrame
? pFrame
->GetViewShell() : nullptr;
2329 GetMedium()->SignContents_Impl(pDialogParent
,
2330 false, HasValidSignatures(), pViewShell
, [this, pFrame
](bool bSignSuccess
) {
2331 AfterSigning(bSignSuccess
, false);
2333 // Reload the document to get the updated graphic
2334 // FIXME: Update just the signature line graphic instead of reloading the document
2336 pFrame
->GetDispatcher()->Execute(SID_RELOAD
);
2337 }, aSignatureLineId
, xCert
, xValidGraphic
, xInvalidGraphic
, aComment
);
2340 SignatureState
SfxObjectShell::GetScriptingSignatureState()
2342 return ImplGetSignatureState( true );
2345 void SfxObjectShell::SignScriptingContent(weld::Window
* pDialogParent
, const std::function
<void(bool)>& rCallback
)
2347 if (!PrepareForSigning(pDialogParent
))
2353 if (CheckIsReadonly(true, pDialogParent
))
2359 SfxViewFrame
* pFrame
= GetFrame();
2360 SfxViewShell
* pViewShell
= pFrame
? pFrame
->GetViewShell() : nullptr;
2361 GetMedium()->SignContents_Impl(pDialogParent
, true, HasValidSignatures(), pViewShell
, [this, rCallback
](bool bSignSuccess
) {
2362 AfterSigning(bSignSuccess
, true);
2364 rCallback(bSignSuccess
);
2368 const uno::Sequence
<sal_Int8
>& SfxObjectShell::getUnoTunnelId()
2370 static const comphelper::UnoIdInit theSfxObjectShellUnoTunnelId
;
2371 return theSfxObjectShellUnoTunnelId
.getSeq();
2374 uno::Sequence
< beans::PropertyValue
> SfxObjectShell::GetDocumentProtectionFromGrabBag() const
2376 uno::Reference
<frame::XModel
> xModel
= GetBaseModel();
2380 return uno::Sequence
< beans::PropertyValue
>();
2383 uno::Reference
< beans::XPropertySet
> xPropSet( xModel
, uno::UNO_QUERY_THROW
);
2384 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo
= xPropSet
->getPropertySetInfo();
2385 const OUString aGrabBagName
= UNO_NAME_MISC_OBJ_INTEROPGRABBAG
;
2386 if ( xPropSetInfo
->hasPropertyByName( aGrabBagName
) )
2388 uno::Sequence
< beans::PropertyValue
> propList
;
2389 xPropSet
->getPropertyValue( aGrabBagName
) >>= propList
;
2390 for (const auto& rProp
: propList
)
2392 if (rProp
.Name
== "DocumentProtection")
2394 uno::Sequence
< beans::PropertyValue
> rAttributeList
;
2395 rProp
.Value
>>= rAttributeList
;
2396 return rAttributeList
;
2401 return uno::Sequence
< beans::PropertyValue
>();
2404 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */