From 426c641976688e3e4d1ce66f76b27ccbd2dca55a Mon Sep 17 00:00:00 2001 From: Sarper Akdemir Date: Wed, 17 Jul 2024 12:47:22 +0200 Subject: [PATCH] tdf#159040: add sign with default certificate to save dialog Include X.509 certificates under Tools->Options->UserData among the keys for signing. Add a new checkbox to Save file dialog, to sign with that selected key easily. The checkbox is disabled if there's no matching key found. Change-Id: I9fc16790c479819cd1f35bcad040d0ebc7c4bdef Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170619 Tested-by: Jenkins Reviewed-by: Sarper Akdemir --- comphelper/source/misc/xmlsechelper.cxx | 29 +++++++++ cui/source/options/optgenrl.cxx | 44 ++++++++++--- cui/uiconfig/ui/optuserpage.ui | 4 +- fpicker/source/aqua/ControlHelper.hxx | 1 + fpicker/source/aqua/ControlHelper.mm | 9 +++ fpicker/source/aqua/resourceprovider.mm | 1 + fpicker/source/office/OfficeControlAccess.cxx | 2 + fpicker/source/office/iodlg.cxx | 11 ++++ fpicker/source/office/iodlgimp.hxx | 1 + fpicker/source/win32/VistaFilePicker.cxx | 7 ++ fpicker/source/win32/VistaFilePickerImpl.cxx | 8 +++ fpicker/source/win32/VistaFilePickerImpl.hxx | 1 + fpicker/source/win32/resourceprovider.cxx | 3 +- fpicker/uiconfig/ui/explorerfiledialog.ui | 12 +++- include/comphelper/xmlsechelper.hxx | 14 ++++ include/fpicker/strings.hrc | 1 + include/sfx2/objsh.hxx | 1 + include/sfx2/sfxsids.hrc | 2 +- .../dialogs/ExtendedFilePickerElementIds.idl | 1 + .../schema/org/openoffice/UserProfile.xcs | 2 +- sfx2/source/dialog/filedlghelper.cxx | 64 +++++++++++++++++++ sfx2/source/dialog/filedlgimpl.hxx | 2 + sfx2/source/doc/guisaveas.cxx | 61 ++++++++++++++++++ sfx2/source/doc/objserv.cxx | 25 +++++--- vcl/unx/gtk3/fpicker/SalGtkFilePicker.cxx | 9 +++ vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx | 1 + vcl/unx/gtk3/fpicker/resourceprovider.cxx | 1 + 27 files changed, 293 insertions(+), 24 deletions(-) diff --git a/comphelper/source/misc/xmlsechelper.cxx b/comphelper/source/misc/xmlsechelper.cxx index 2a0a4d2e3198..69dd3b6571bb 100644 --- a/comphelper/source/misc/xmlsechelper.cxx +++ b/comphelper/source/misc/xmlsechelper.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -308,6 +309,34 @@ std::vector< std::pair< OUString, OUString> > parseDN(std::u16string_view rRawSt return aStr.makeStringAndClear(); } + + css::uno::Reference FindCertInContext( + const css::uno::Reference& xSecurityContext, + const OUString& rContentPart) + { + if (!xSecurityContext.is()) + return {}; + + css::uno::Reference xSE + = xSecurityContext->getSecurityEnvironment(); + css::uno::Sequence> xCertificates + = xSE->getPersonalCertificates(); + + auto aCertsIter = asNonConstRange(xCertificates); + + auto pxCert + = std::find_if(aCertsIter.begin(), aCertsIter.end(), + [&rContentPart](auto& xCert) + { + return comphelper::xmlsec::GetContentPart( + xCert->getSubjectName(), xCert->getCertificateKind()) + == rContentPart; + }); + if (pxCert == aCertsIter.end()) + return {}; + + return *pxCert; + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/options/optgenrl.cxx b/cui/source/options/optgenrl.cxx index 54963bb86c97..ff2216b6e41c 100644 --- a/cui/source/options/optgenrl.cxx +++ b/cui/source/options/optgenrl.cxx @@ -25,6 +25,8 @@ # include # include #endif +#include +#include #include #include @@ -300,26 +302,52 @@ void SvxGeneralTabPage::InitCryptography() #if HAVE_FEATURE_GPGME m_xCryptoFrame->show(); - uno::Reference< xml::crypto::XSEInitializer > xSEInitializer; try { - xSEInitializer = xml::crypto::GPGSEInitializer::create( comphelper::getProcessComponentContext() ); - uno::Reference xSC = xSEInitializer->createSecurityContext( OUString() ); - if (xSC.is()) + uno::Reference xSecurityContext + = xml::crypto::SEInitializer::create(comphelper::getProcessComponentContext()) + ->createSecurityContext(""); + uno::Reference xSecurityContextGPG + = xml::crypto::GPGSEInitializer::create(comphelper::getProcessComponentContext()) + ->createSecurityContext(""); + if (xSecurityContextGPG.is()) { - uno::Reference xSE = xSC->getSecurityEnvironment(); + uno::Reference xSE = xSecurityContextGPG->getSecurityEnvironment(); uno::Sequence> xCertificates = xSE->getPersonalCertificates(); if (xCertificates.hasElements()) { for (auto& xCert : asNonConstRange(xCertificates)) { - m_xSigningKeyLB->append_text( xCert->getIssuerName()); - m_xEncryptionKeyLB->append_text( xCert->getIssuerName()); + const auto aIssuer = comphelper::xmlsec::GetContentPart( + xCert->getSubjectName(), xCert->getCertificateKind()); + m_xSigningKeyLB->append_text(aIssuer); + m_xEncryptionKeyLB->append_text(aIssuer); } } + } - //tdf#115015: wrap checkbox text and listboxes if necessary + if (xSecurityContext.is()) + { + uno::Reference xSE = xSecurityContext->getSecurityEnvironment(); + uno::Sequence> xCertificates + = xSE->getPersonalCertificates(); + + if (xCertificates.hasElements()) + { + for (auto& xCert : asNonConstRange(xCertificates)) + { + const auto aIssuer + = comphelper::xmlsec::GetContentPart(xCert->getSubjectName(), + xCert->getCertificateKind()); + m_xSigningKeyLB->append_text(aIssuer); + } + } + } + + if (xSecurityContext.is() || xSecurityContextGPG.is()) + { + //tdf#115015: wrap checkbox text and listboxes if necessary int nPrefWidth(m_xEncryptToSelfCB->get_preferred_size().Width()); int nMaxWidth = m_xEncryptToSelfCB->get_approximate_digit_width() * 40; if (nPrefWidth > nMaxWidth) diff --git a/cui/uiconfig/ui/optuserpage.ui b/cui/uiconfig/ui/optuserpage.ui index a3399ae49739..0c69fb176123 100644 --- a/cui/uiconfig/ui/optuserpage.ui +++ b/cui/uiconfig/ui/optuserpage.ui @@ -1098,7 +1098,7 @@ True False - _OpenPGP signing key: + _Signing key: True signingkey 0 @@ -1151,7 +1151,7 @@ - Select your OpenPGP key from the drop-down list for signing ODF documents. + Select your key from the drop-down list for signing ODF documents. diff --git a/fpicker/source/aqua/ControlHelper.hxx b/fpicker/source/aqua/ControlHelper.hxx index ede5d0b0d574..20bea4f0b48d 100644 --- a/fpicker/source/aqua/ControlHelper.hxx +++ b/fpicker/source/aqua/ControlHelper.hxx @@ -70,6 +70,7 @@ public: AUTOEXTENSION, //but autoextension is handled differently on MacOSX PASSWORD, GPGENCRYPTION, + GPGSIGN, FILTEROPTIONS, READONLY, LINK, diff --git a/fpicker/source/aqua/ControlHelper.mm b/fpicker/source/aqua/ControlHelper.mm index 46c8c549035f..ef8c00cdbc79 100644 --- a/fpicker/source/aqua/ControlHelper.mm +++ b/fpicker/source/aqua/ControlHelper.mm @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include #include #include #include @@ -185,11 +186,17 @@ void ControlHelper::initialize( sal_Int16 nTemplateId ) m_bToggleVisibility[AUTOEXTENSION] = true; m_bToggleVisibility[PASSWORD] = true; m_bToggleVisibility[GPGENCRYPTION] = true; +#if HAVE_FEATURE_GPGME + m_bToggleVisibility[GPGSIGN] = true; +#endif break; case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: m_bToggleVisibility[AUTOEXTENSION] = true; m_bToggleVisibility[PASSWORD] = true; m_bToggleVisibility[GPGENCRYPTION] = true; +#if HAVE_FEATURE_GPGME + m_bToggleVisibility[GPGSIGN] = true; +#endif m_bToggleVisibility[FILTEROPTIONS] = true; break; case FILESAVE_AUTOEXTENSION_SELECTION: @@ -605,6 +612,7 @@ int ControlHelper::getControlElementName(const Class aClazz, const int nControlI TOGGLE_ELEMENT( AUTOEXTENSION ); TOGGLE_ELEMENT( PASSWORD ); TOGGLE_ELEMENT( GPGENCRYPTION ); + TOGGLE_ELEMENT( GPGSIGN ); TOGGLE_ELEMENT( FILTEROPTIONS ); TOGGLE_ELEMENT( READONLY ); TOGGLE_ELEMENT( LINK ); @@ -729,6 +737,7 @@ case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \ MAP_TOGGLE( AUTOEXTENSION ); MAP_TOGGLE( PASSWORD ); MAP_TOGGLE( GPGENCRYPTION ); + MAP_TOGGLE( GPGSIGN ); MAP_TOGGLE( FILTEROPTIONS ); MAP_TOGGLE( READONLY ); MAP_TOGGLE( LINK ); diff --git a/fpicker/source/aqua/resourceprovider.mm b/fpicker/source/aqua/resourceprovider.mm index e3aa23a6f64e..ae330251f5e0 100644 --- a/fpicker/source/aqua/resourceprovider.mm +++ b/fpicker/source/aqua/resourceprovider.mm @@ -51,6 +51,7 @@ Entry const CtrlIdToResIdTable[] = { { CHECKBOX_AUTOEXTENSION, STR_SVT_FILEPICKER_AUTO_EXTENSION }, { CHECKBOX_PASSWORD, STR_SVT_FILEPICKER_PASSWORD }, { CHECKBOX_GPGENCRYPTION, STR_SVT_FILEPICKER_GPGENCRYPT }, + { CHECKBOX_GPGSIGN, STR_SVT_FILEPICKER_GPGSIGN }, { CHECKBOX_FILTEROPTIONS, STR_SVT_FILEPICKER_FILTER_OPTIONS }, { CHECKBOX_READONLY, STR_SVT_FILEPICKER_READONLY }, { CHECKBOX_LINK, STR_SVT_FILEPICKER_INSERT_AS_LINK }, diff --git a/fpicker/source/office/OfficeControlAccess.cxx b/fpicker/source/office/OfficeControlAccess.cxx index 6cde40fb48cd..c9675f77431f 100644 --- a/fpicker/source/office/OfficeControlAccess.cxx +++ b/fpicker/source/office/OfficeControlAccess.cxx @@ -79,6 +79,7 @@ namespace svt { "FilterListLabel", LISTBOX_FILTER_LABEL, PROPERTY_FLAGS_COMMON | PropFlags::Text }, { "FilterOptionsBox", CHECKBOX_FILTEROPTIONS, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, { "GpgPassword", CHECKBOX_GPGENCRYPTION, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, + { "GpgSign", CHECKBOX_GPGSIGN, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX }, { "HelpButton", PUSHBUTTON_HELP, PROPERTY_FLAGS_COMMON | PropFlags::Text }, { "ImageAnchorList", LISTBOX_IMAGE_ANCHOR, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_LISTBOX }, { "ImageAnchorListLabel", LISTBOX_IMAGE_ANCHOR_LABEL, PROPERTY_FLAGS_COMMON | PropFlags::Text }, @@ -399,6 +400,7 @@ namespace svt case CHECKBOX_AUTOEXTENSION: case CHECKBOX_PASSWORD: case CHECKBOX_GPGENCRYPTION: + case CHECKBOX_GPGSIGN: case CHECKBOX_FILTEROPTIONS: case CHECKBOX_READONLY: case CHECKBOX_LINK: diff --git a/fpicker/source/office/iodlg.cxx b/fpicker/source/office/iodlg.cxx index d154cb928832..cbfdd441329b 100644 --- a/fpicker/source/office/iodlg.cxx +++ b/fpicker/source/office/iodlg.cxx @@ -302,6 +302,7 @@ SvtFileDialog::SvtFileDialog(weld::Window* pParent, PickerFlags nStyle) m_xImpl->m_xBtnNewFolder = m_xBuilder->weld_button(u"new_folder"_ustr); m_xImpl->m_xCbPassword = m_xBuilder->weld_check_button(u"password"_ustr); m_xImpl->m_xCbGPGEncrypt = m_xBuilder->weld_check_button(u"gpgencrypt"_ustr); + m_xImpl->m_xCbGPGSign = m_xBuilder->weld_check_button(u"gpgsign"_ustr); m_xImpl->m_xCbAutoExtension = m_xBuilder->weld_check_button(u"extension"_ustr); m_xImpl->m_xSharedLabel = m_xBuilder->weld_label(u"shared_label"_ustr); m_xImpl->m_xSharedListBox = m_xBuilder->weld_combo_box(u"shared"_ustr); @@ -367,8 +368,12 @@ SvtFileDialog::SvtFileDialog(weld::Window* pParent, PickerFlags nStyle) m_xImpl->m_xCbPassword->set_label( FpsResId( STR_SVT_FILEPICKER_PASSWORD ) ); m_xImpl->m_xCbPassword->connect_toggled( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); m_xImpl->m_xCbPassword->show(); + m_xImpl->m_xCbGPGEncrypt->connect_toggled( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); m_xImpl->m_xCbGPGEncrypt->show(); + + m_xImpl->m_xCbGPGSign->connect_toggled( LINK( this, SvtFileDialog, ClickHdl_Impl ) ); + m_xImpl->m_xCbGPGSign->show(); } // set the ini file for extracting the size @@ -1240,6 +1245,8 @@ IMPL_LINK( SvtFileDialog, ClickHdl_Impl, weld::Toggleable&, rCheckBox, void ) nId = CHECKBOX_PASSWORD; else if ( &rCheckBox == m_xImpl->m_xCbGPGEncrypt.get() ) nId = CHECKBOX_GPGENCRYPTION; + else if ( &rCheckBox == m_xImpl->m_xCbGPGSign.get() ) + nId = CHECKBOX_GPGSIGN; else if ( &rCheckBox == m_xCbLinkBox.get() ) nId = CHECKBOX_LINK; else if ( &rCheckBox == m_xCbPreviewBox.get() ) @@ -1918,6 +1925,10 @@ weld::Widget* SvtFileDialog::getControl( sal_Int16 nControlId, bool bLabelContro pReturn = m_xImpl->m_xCbGPGEncrypt.get(); break; + case CHECKBOX_GPGSIGN: + pReturn = m_xImpl->m_xCbGPGSign.get(); + break; + case CHECKBOX_FILTEROPTIONS: pReturn = m_xImpl->m_xCbOptions.get(); break; diff --git a/fpicker/source/office/iodlgimp.hxx b/fpicker/source/office/iodlgimp.hxx index 3a02dbbee641..11a9e89d2642 100644 --- a/fpicker/source/office/iodlgimp.hxx +++ b/fpicker/source/office/iodlgimp.hxx @@ -127,6 +127,7 @@ public: std::unique_ptr m_xBtnNewFolder; std::unique_ptr m_xCbPassword; std::unique_ptr m_xCbGPGEncrypt; + std::unique_ptr m_xCbGPGSign; std::unique_ptr m_xEdCurrentPath; std::unique_ptr m_xCbAutoExtension; std::unique_ptr m_xCbOptions; diff --git a/fpicker/source/win32/VistaFilePicker.cxx b/fpicker/source/win32/VistaFilePicker.cxx index 743dcda5d080..ac35296f12fb 100644 --- a/fpicker/source/win32/VistaFilePicker.cxx +++ b/fpicker/source/win32/VistaFilePicker.cxx @@ -18,6 +18,7 @@ */ #include +#include #include "VistaFilePicker.hxx" @@ -362,6 +363,9 @@ void SAL_CALL VistaFilePicker::initialize(const css::uno::Sequence< css::uno::An nFeatures |= FEATURE_AUTOEXTENSION; nFeatures |= FEATURE_PASSWORD; nFeatures |= FEATURE_GPGPASSWORD; +#if HAVE_FEATURE_GPGME + nFeatures |= FEATURE_GPGSIGN; +#endif } break; @@ -372,6 +376,9 @@ void SAL_CALL VistaFilePicker::initialize(const css::uno::Sequence< css::uno::An nFeatures |= FEATURE_PASSWORD; nFeatures |= FEATURE_FILTEROPTIONS; nFeatures |= FEATURE_GPGPASSWORD; +#if HAVE_FEATURE_GPGME + nFeatures |= FEATURE_GPGSIGN; +#endif } break; diff --git a/fpicker/source/win32/VistaFilePickerImpl.cxx b/fpicker/source/win32/VistaFilePickerImpl.cxx index a3ee8c9ad3e2..3ffe0883d128 100644 --- a/fpicker/source/win32/VistaFilePickerImpl.cxx +++ b/fpicker/source/win32/VistaFilePickerImpl.cxx @@ -641,6 +641,13 @@ void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_I setLabelToControl(iCustom, nControlId); } + if ((nFeatures & FEATURE_GPGSIGN) == FEATURE_GPGSIGN) + { + nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_GPGSIGN; + iCustom->AddCheckButton (nControlId, L"GpgSign", false); + setLabelToControl(iCustom, nControlId); + } + if ((nFeatures & FEATURE_READONLY) == FEATURE_READONLY) { nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY; @@ -1093,6 +1100,7 @@ void VistaFilePickerImpl::impl_sta_GetControlValue(Request& rRequest) { case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD : case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION : + case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_GPGSIGN : case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY : case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS : case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK : diff --git a/fpicker/source/win32/VistaFilePickerImpl.hxx b/fpicker/source/win32/VistaFilePickerImpl.hxx index 8ea9468076ea..f2cb2c27427e 100644 --- a/fpicker/source/win32/VistaFilePickerImpl.hxx +++ b/fpicker/source/win32/VistaFilePickerImpl.hxx @@ -56,6 +56,7 @@ const ::sal_Int32 FEATURE_READONLY = 512; const ::sal_Int32 FEATURE_VERSION = 1024; const ::sal_Int32 FEATURE_GPGPASSWORD = 2048; const ::sal_Int32 FEATURE_IMAGEANCHOR = 4096; +const ::sal_Int32 FEATURE_GPGSIGN = 8192; inline constexpr OUString PROP_PICKER_LISTENER(u"picker_listener"_ustr ); // [XFilePickerListenert] inline constexpr OUString PROP_DIALOG_SHOW_RESULT(u"dialog_show_result"_ustr ); // [sal_Bool] true=OK, false=CANCEL diff --git a/fpicker/source/win32/resourceprovider.cxx b/fpicker/source/win32/resourceprovider.cxx index 3515e9432146..d3ac79002340 100644 --- a/fpicker/source/win32/resourceprovider.cxx +++ b/fpicker/source/win32/resourceprovider.cxx @@ -66,7 +66,8 @@ Entry const CtrlIdToResIdTable[] = { { CHECKBOX_SELECTION, STR_SVT_FILEPICKER_SELECTION }, { FOLDERPICKER_TITLE, STR_SVT_FOLDERPICKER_DEFAULT_TITLE }, { FOLDER_PICKER_DEF_DESCRIPTION, STR_SVT_FOLDERPICKER_DEFAULT_DESCRIPTION }, - { CHECKBOX_GPGENCRYPTION, STR_SVT_FILEPICKER_GPGENCRYPT } + { CHECKBOX_GPGENCRYPTION, STR_SVT_FILEPICKER_GPGENCRYPT }, + { CHECKBOX_GPGSIGN, STR_SVT_FILEPICKER_GPGSIGN } }; const sal_Int32 SIZE_TABLE = SAL_N_ELEMENTS( CtrlIdToResIdTable ); diff --git a/fpicker/uiconfig/ui/explorerfiledialog.ui b/fpicker/uiconfig/ui/explorerfiledialog.ui index 238760f74d13..8f49cbd4620e 100644 --- a/fpicker/uiconfig/ui/explorerfiledialog.ui +++ b/fpicker/uiconfig/ui/explorerfiledialog.ui @@ -755,7 +755,17 @@ - + + Sign with default certificate + True + False + True + True + + + 1 + 1 + diff --git a/include/comphelper/xmlsechelper.hxx b/include/comphelper/xmlsechelper.hxx index 9a245877f6ae..40c5599c8b57 100644 --- a/include/comphelper/xmlsechelper.hxx +++ b/include/comphelper/xmlsechelper.hxx @@ -27,6 +27,16 @@ #include +namespace com::sun::star::xml::crypto +{ +class XXMLSecurityContext; +} + +namespace com::sun::star::security +{ +class XCertificate; +} + namespace comphelper::xmlsec { COMPHELPER_DLLPUBLIC OUString GetCertificateKind(const css::security::CertificateKind& rKind); @@ -40,6 +50,10 @@ COMPHELPER_DLLPUBLIC OUString GetContentPart(const OUString& _rRawString, COMPHELPER_DLLPUBLIC OUString GetHexString(const css::uno::Sequence& _rSeq, const char* _pSep, sal_uInt16 _nLineBreak = 0xFFFF); + +COMPHELPER_DLLPUBLIC css::uno::Reference FindCertInContext( + const css::uno::Reference& xSecurityContext, + const OUString& rContentPart); } #endif diff --git a/include/fpicker/strings.hrc b/include/fpicker/strings.hrc index 004a06a53f5d..e344ffb118f9 100644 --- a/include/fpicker/strings.hrc +++ b/include/fpicker/strings.hrc @@ -15,6 +15,7 @@ #define STR_SVT_FILEPICKER_PASSWORD NC_("STR_SVT_FILEPICKER_PASSWORD", "Save with pass~word") //dear loplugins, please don't remove this constant, it will be used in follow-up commits #define STR_SVT_FILEPICKER_GPGENCRYPT NC_("STR_SVT_FILEPICKER_GPGENCRYPT", "Encrypt with ~GPG key") +#define STR_SVT_FILEPICKER_GPGSIGN NC_("STR_SVT_FILEPICKER_GPGSIGN", "Sign with ~default certificate") #define STR_SVT_FILEPICKER_FILTER_OPTIONS NC_("STR_SVT_FILEPICKER_FILTER_OPTIONS", "~Edit filter settings") #define STR_SVT_FILEPICKER_READONLY NC_("STR_SVT_FILEPICKER_READONLY", "~Read-only") #define STR_SVT_FILEPICKER_INSERT_AS_LINK NC_("STR_SVT_FILEPICKER_INSERT_AS_LINK", "~Link") diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx index 562bca9bc927..d58b87a56664 100644 --- a/include/sfx2/objsh.hxx +++ b/include/sfx2/objsh.hxx @@ -477,6 +477,7 @@ public: bool IsAvoidRecentDocs() const { return mbAvoidRecentDocs; } bool IsRememberingSignature() const { return bRememberSignature; } + void SetRememberCurrentSignature(bool bRemember); /// Don't add to the recent documents - it's an expensive operation, sometimes it is not wanted. void AvoidRecentDocs(bool bAvoid) { mbAvoidRecentDocs = bAvoid; } diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc index 2c20b3d8b81a..4356ede80ef3 100644 --- a/include/sfx2/sfxsids.hrc +++ b/include/sfx2/sfxsids.hrc @@ -301,7 +301,7 @@ class SvxZoomItem; #define FN_CHANGE_THEME (SID_SFX_START + 1745) #define FN_PARAM_NEW_THEME TypedWhichId(SID_SFX_START + 1746) #define SID_OPTIONS_PAGEID TypedWhichId(SID_SFX_START + 1747) - +#define SID_GPGSIGN TypedWhichId(SID_SFX_START + 1748) // SID_SFX_free_END (SID_SFX_START + 3999) #define SID_OPEN_NEW_VIEW TypedWhichId(SID_SFX_START + 520) diff --git a/offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl b/offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl index 52dadce3252b..eafaf03d75e6 100644 --- a/offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl +++ b/offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl @@ -49,6 +49,7 @@ published constants ExtendedFilePickerElementIds /** @since LibreOffice 6.0 */ const short CHECKBOX_GPGENCRYPTION = 211; /** @since LibreOffice 6.1 */ const short LISTBOX_IMAGE_ANCHOR = 212; /** @since LibreOffice 6.1 */ const short LISTBOX_IMAGE_ANCHOR_LABEL = 213; + /** @since LibreOffice 25.2 */ const short CHECKBOX_GPGSIGN = 214; }; diff --git a/officecfg/registry/schema/org/openoffice/UserProfile.xcs b/officecfg/registry/schema/org/openoffice/UserProfile.xcs index 0b458c0e24e9..3b0927d1341e 100644 --- a/officecfg/registry/schema/org/openoffice/UserProfile.xcs +++ b/officecfg/registry/schema/org/openoffice/UserProfile.xcs @@ -170,7 +170,7 @@ - Specifies user's preferred OpenPGP key used for document signing. + Specifies user's preferred key used for document signing. diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx index b54d65f7db2b..b2376a2b7e5d 100644 --- a/sfx2/source/dialog/filedlghelper.cxx +++ b/sfx2/source/dialog/filedlghelper.cxx @@ -96,6 +96,15 @@ #include #include +#include +#if HAVE_FEATURE_GPGME +# include +# include +# include +#endif +#include +#include + #ifdef UNX #include #include @@ -284,6 +293,7 @@ void FileDialogHelper_Impl::handleControlStateChanged( const FilePickerEvent& aE enablePasswordBox( false ); enableGpgEncrBox( false ); updateSelectionBox(); + updateSignByDefault(); // only use it for export and with our own dialog if ( mbExport && !mbSystemPicker ) updateExportButton(); @@ -508,6 +518,43 @@ void FileDialogHelper_Impl::updateSelectionBox() } } +void FileDialogHelper_Impl::updateSignByDefault() +{ +#if HAVE_FEATURE_GPGME + if (!mbHasSignByDefault) + return; + + auto HaveMatchingUserSigningKey = []() -> bool + { + auto aSigningKey = SvtUserOptions{}.GetSigningKey(); + if (aSigningKey.isEmpty()) + return false; + + std::vector> xSecurityContexts{ + xml::crypto::SEInitializer::create(comphelper::getProcessComponentContext()) + ->createSecurityContext({}), + xml::crypto::GPGSEInitializer::create(comphelper::getProcessComponentContext()) + ->createSecurityContext({}), + }; + + for (const auto& xSecurityContext : xSecurityContexts) + { + if (xSecurityContext.is()) + { + css::uno::Reference xCert + = comphelper::xmlsec::FindCertInContext(xSecurityContext, aSigningKey); + if (xCert.is()) + return true; + } + } + return false; + }; + + updateExtendedControl(ExtendedFilePickerElementIds::CHECKBOX_GPGSIGN, + HaveMatchingUserSigningKey()); +#endif +} + void FileDialogHelper_Impl::enablePasswordBox( bool bInit ) { if ( ! mbHasPassword ) @@ -918,6 +965,7 @@ FileDialogHelper_Impl::FileDialogHelper_Impl( mpAntiImpl = _pAntiImpl; mbHasAutoExt = false; mbHasPassword = false; + mbHasSignByDefault = false; m_bHaveFilterOptions = false; mbIsPwdEnabled = true; mbIsGpgEncrEnabled = true; @@ -982,6 +1030,7 @@ FileDialogHelper_Impl::FileDialogHelper_Impl( mbHasPassword = true; mbHasAutoExt = true; mbIsSaveDlg = true; + mbHasSignByDefault = true; break; case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: @@ -998,6 +1047,7 @@ FileDialogHelper_Impl::FileDialogHelper_Impl( mbHasAutoExt = true; mbIsSaveDlg = true; + mbHasSignByDefault = true; break; case FILESAVE_AUTOEXTENSION_SELECTION: @@ -1257,6 +1307,7 @@ IMPL_LINK_NOARG( FileDialogHelper_Impl, InitControls, void*, void ) enableGpgEncrBox( true ); updateFilterOptionsBox( ); updateSelectionBox( ); + updateSignByDefault(); } void FileDialogHelper_Impl::preExecute() @@ -1606,6 +1657,19 @@ ErrCode FileDialogHelper_Impl::execute( std::vector& rpURLList, } catch( const IllegalArgumentException& ){} } + if ( pCurrentFilter && xCtrlAccess.is() ) + { + try + { + Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_GPGSIGN, 0 ); + bool bSign = false; + if ((aValue >>= bSign) && bSign) + { + rpSet->Put(SfxBoolItem(SID_GPGSIGN, bSign)); + } + } + catch( const IllegalArgumentException& ){} + } SaveLastUsedFilter(); return ERRCODE_NONE; diff --git a/sfx2/source/dialog/filedlgimpl.hxx b/sfx2/source/dialog/filedlgimpl.hxx index 60fb312e2b17..ce6770cff107 100644 --- a/sfx2/source/dialog/filedlgimpl.hxx +++ b/sfx2/source/dialog/filedlgimpl.hxx @@ -95,6 +95,7 @@ namespace sfx2 bool mbSelectionEnabled : 1; bool mbHasSelectionBox : 1; bool mbSelectionFltrEnabled : 1; + bool mbHasSignByDefault : 1; private: void addFilters( const OUString& rFactory, @@ -108,6 +109,7 @@ namespace sfx2 void updateFilterOptionsBox(); void updateExportButton(); void updateSelectionBox(); + void updateSignByDefault(); void updateVersions(); void updatePreviewState( bool _bUpdatePreviewWindow ); void dispose(); diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx index ce31ee2da6f7..eee91ba06a38 100644 --- a/sfx2/source/doc/guisaveas.cxx +++ b/sfx2/source/doc/guisaveas.cxx @@ -16,6 +16,14 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include +#if HAVE_FEATURE_GPGME +#include +#include +#include +#endif +#include +#include #include #include @@ -63,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -275,6 +284,7 @@ class ModelData_Impl ::comphelper::SequenceAsHashMap m_aMediaDescrHM; bool m_bRecommendReadOnly; + bool m_bSignWithDefaultSignature; DECL_LINK(OptionsDialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, void); @@ -294,6 +304,7 @@ public: ::comphelper::SequenceAsHashMap& GetMediaDescr() { return m_aMediaDescrHM; } bool IsRecommendReadOnly() const { return m_bRecommendReadOnly; } + bool IsSignWithDefaultSignature() const { return m_bSignWithDefaultSignature; } const ::comphelper::SequenceAsHashMap& GetDocProps(); @@ -1093,6 +1104,10 @@ bool ModelData_Impl::OutputFileDialog( sal_Int16 nStoreMode, m_bRecommendReadOnly = ( pRecommendReadOnly && pRecommendReadOnly->GetValue() ); pDialogParams->ClearItem( SID_RECOMMENDREADONLY ); + const SfxBoolItem* pSignWithDefaultKey = SfxItemSet::GetItem(&*pDialogParams, SID_GPGSIGN, false); + m_bSignWithDefaultSignature = (pSignWithDefaultKey && pSignWithDefaultKey->GetValue()); + pDialogParams->ClearItem( SID_GPGSIGN ); + uno::Sequence< beans::PropertyValue > aPropsFromDialog; TransformItems( nSlotID, *pDialogParams, aPropsFromDialog ); GetMediaDescr() << aPropsFromDialog; @@ -1878,6 +1893,52 @@ bool SfxStoringHelper::FinishGUIStoreModel(::comphelper::SequenceAsHashMap::cons #endif } + if (aModelData.IsSignWithDefaultSignature()) + { + auto SignWithDefaultSignature = [&]() + { +#if HAVE_FEATURE_GPGME + auto aSigningKey = SvtUserOptions().GetSigningKey(); + if (aSigningKey.isEmpty()) + return; + + std::vector> xSecurityContexts{ + xml::crypto::SEInitializer::create(comphelper::getProcessComponentContext()) + ->createSecurityContext({}), + xml::crypto::GPGSEInitializer::create(comphelper::getProcessComponentContext()) + ->createSecurityContext({}), + }; + + for (const auto& xSecurityContext : xSecurityContexts) + { + if (xSecurityContext.is()) + { + css::uno::Reference xCert + = comphelper::xmlsec::FindCertInContext(xSecurityContext, aSigningKey); + + if (xCert.is() && SfxViewShell::Current()) + { + SfxObjectShell* pDocShell = SfxViewShell::Current()->GetObjectShell(); + bool bSigned = pDocShell->SignDocumentContentUsingCertificate(xCert); + if (bSigned && pDocShell->HasValidSignatures()) + { + std::unique_ptr xBox( + Application::CreateMessageDialog( + SfxStoringHelper::GetModelWindow(aModelData.GetModel()), + VclMessageType::Question, VclButtonsType::YesNo, + SfxResId(STR_QUERY_REMEMBERSIGNATURE))); + pDocShell->SetRememberCurrentSignature(xBox->run() == RET_YES); + } + return; + } + } + } + return; +#endif + }; + SignWithDefaultSignature(); + } + // Launch PDF viewer if ( nStoreMode & PDFEXPORT_REQUESTED && !comphelper::LibreOfficeKit::isActive() ) { diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx index 555e57492801..26301eb1cb6d 100644 --- a/sfx2/source/doc/objserv.cxx +++ b/sfx2/source/doc/objserv.cxx @@ -600,16 +600,7 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) { std::unique_ptr xBox(Application::CreateMessageDialog( pDialogParent, VclMessageType::Question, VclButtonsType::YesNo, SfxResId(STR_QUERY_REMEMBERSIGNATURE))); - if (xBox->run() == RET_YES) - { - rSignatureInfosRemembered = GetDocumentSignatureInformation(false); - bRememberSignature = true; - } - else - { - rSignatureInfosRemembered = uno::Sequence< security::DocumentSignatureInformation >(); - bRememberSignature = false; - } + SetRememberCurrentSignature(xBox->run() == RET_YES); } return; @@ -1899,6 +1890,20 @@ uno::Sequence< security::DocumentSignatureInformation > SfxObjectShell::GetDocum return aResult; } +void SfxObjectShell::SetRememberCurrentSignature(bool bRemember) +{ + if (bRemember) + { + rSignatureInfosRemembered = GetDocumentSignatureInformation(false); + bRememberSignature = true; + } + else + { + rSignatureInfosRemembered = uno::Sequence(); + bRememberSignature = false; + } +} + SignatureState SfxObjectShell::ImplGetSignatureState( bool bScriptingContent ) { SignatureState* pState = bScriptingContent ? &pImpl->nScriptingSignatureState : &pImpl->nDocumentSignatureState; diff --git a/vcl/unx/gtk3/fpicker/SalGtkFilePicker.cxx b/vcl/unx/gtk3/fpicker/SalGtkFilePicker.cxx index 3685f229e6d2..3dcc32a4c88e 100644 --- a/vcl/unx/gtk3/fpicker/SalGtkFilePicker.cxx +++ b/vcl/unx/gtk3/fpicker/SalGtkFilePicker.cxx @@ -18,6 +18,7 @@ */ #include +#include #include #include @@ -201,6 +202,7 @@ SalGtkFilePicker::SalGtkFilePicker( const uno::Reference< uno::XComponentContext LABEL_TOGGLE( AUTOEXTENSION ); LABEL_TOGGLE( PASSWORD ); LABEL_TOGGLE( GPGENCRYPTION ); + LABEL_TOGGLE( GPGSIGN ); LABEL_TOGGLE( FILTEROPTIONS ); LABEL_TOGGLE( READONLY ); LABEL_TOGGLE( LINK ); @@ -1118,6 +1120,7 @@ GtkWidget *SalGtkFilePicker::getWidget( sal_Int16 nControlId, GType *pType ) MAP_TOGGLE( AUTOEXTENSION ); MAP_TOGGLE( PASSWORD ); MAP_TOGGLE( GPGENCRYPTION ); + MAP_TOGGLE( GPGSIGN ); MAP_TOGGLE( FILTEROPTIONS ); MAP_TOGGLE( READONLY ); MAP_TOGGLE( LINK ); @@ -1698,6 +1701,9 @@ void SalGtkFilePicker::impl_initialize(GtkWidget* pParentWidget, sal_Int16 templ first_button_text = sSave.getStr(); mbToggleVisibility[PASSWORD] = true; mbToggleVisibility[GPGENCRYPTION] = true; +#if HAVE_FEATURE_GPGME + mbToggleVisibility[GPGSIGN] = true; +#endif // TODO break; case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: @@ -1705,6 +1711,9 @@ void SalGtkFilePicker::impl_initialize(GtkWidget* pParentWidget, sal_Int16 templ first_button_text = sSave.getStr(); mbToggleVisibility[PASSWORD] = true; mbToggleVisibility[GPGENCRYPTION] = true; +#if HAVE_FEATURE_GPGME + mbToggleVisibility[GPGSIGN] = true; +#endif mbToggleVisibility[FILTEROPTIONS] = true; // TODO break; diff --git a/vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx b/vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx index fdc701a20384..93c9d818e755 100644 --- a/vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx +++ b/vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx @@ -162,6 +162,7 @@ class SalGtkFilePicker : public SalGtkPicker, public SalGtkFilePicker_Base PREVIEW, SELECTION, GPGENCRYPTION, + GPGSIGN, TOGGLE_LAST }; diff --git a/vcl/unx/gtk3/fpicker/resourceprovider.cxx b/vcl/unx/gtk3/fpicker/resourceprovider.cxx index fa90b8126627..eb97bb3aafaf 100644 --- a/vcl/unx/gtk3/fpicker/resourceprovider.cxx +++ b/vcl/unx/gtk3/fpicker/resourceprovider.cxx @@ -37,6 +37,7 @@ const struct { CHECKBOX_AUTOEXTENSION, STR_SVT_FILEPICKER_AUTO_EXTENSION }, { CHECKBOX_PASSWORD, STR_SVT_FILEPICKER_PASSWORD }, { CHECKBOX_GPGENCRYPTION, STR_SVT_FILEPICKER_GPGENCRYPT }, + { CHECKBOX_GPGSIGN, STR_SVT_FILEPICKER_GPGSIGN }, { CHECKBOX_FILTEROPTIONS, STR_SVT_FILEPICKER_FILTER_OPTIONS }, { CHECKBOX_READONLY, STR_SVT_FILEPICKER_READONLY }, { CHECKBOX_LINK, STR_SVT_FILEPICKER_INSERT_AS_LINK },