Allow selecting a custom certificate manager

Added a new option in Tools>Options>Security that allows choosing the
path of a different certificate manager.

Made Certificate Manager Button be disabled instead of hidden in case no
certificate manager is detected. Added a box notifying that the
certificate manager is opened (or not working in case it failed for some
reason).

Change-Id: I64a901766d4fb05c59c0f85fdf94c08a3ca4bdab
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153798
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
diff --git a/cui/source/options/optinet2.cxx b/cui/source/options/optinet2.cxx
index 95d0ec1..cf879d0 100644
--- a/cui/source/options/optinet2.cxx
+++ b/cui/source/options/optinet2.cxx
@@ -493,6 +493,8 @@ SvxSecurityTabPage::SvxSecurityTabPage(weld::Container* pPage, weld::DialogContr
    , m_xTSAURLsFrame(m_xBuilder->weld_container("tsaurls"))
    , m_xTSAURLsPB(m_xBuilder->weld_button("tsas"))
    , m_xNoPasswordSaveFT(m_xBuilder->weld_label("nopasswordsave"))
    , m_xCertMgrPathLB(m_xBuilder->weld_button("browse"))
    , m_xParameterEdit(m_xBuilder->weld_entry("parameterfield"))
{
    //fdo#65595, we need height-for-width support here, but for now we can
    //bodge it
@@ -516,10 +518,46 @@ SvxSecurityTabPage::SvxSecurityTabPage(weld::Container* pPage, weld::DialogContr
    m_xMacroSecPB->connect_clicked( LINK( this, SvxSecurityTabPage, MacroSecPBHdl ) );
    m_xCertPathPB->connect_clicked( LINK( this, SvxSecurityTabPage, CertPathPBHdl ) );
    m_xTSAURLsPB->connect_clicked( LINK( this, SvxSecurityTabPage, TSAURLsPBHdl ) );
    m_xCertMgrPathLB->connect_clicked( LINK( this, SvxSecurityTabPage, CertMgrPBHdl ) );

    ActivatePage( rSet );
}

IMPL_LINK_NOARG(SvxSecurityTabPage, CertMgrPBHdl, weld::Button&, void)
{
    try
    {
        FileDialogHelper aHelper(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
                                 FileDialogFlags::NONE, nullptr);
        OUString sPath = m_xParameterEdit->get_text();
        if (sPath.isEmpty())
            sPath = "/usr/bin";

        OUString sUrl;
        osl::FileBase::getFileURLFromSystemPath(sPath, sUrl);
        aHelper.SetDisplayDirectory(sUrl);

        if (ERRCODE_NONE == aHelper.Execute())
        {
            sUrl = aHelper.GetPath();
            if (osl::FileBase::getSystemPathFromFileURL(sUrl, sPath) != osl::FileBase::E_None)
            {
                sPath.clear();
            }
            m_xParameterEdit->set_text(sPath);
        }
        std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
            comphelper::ConfigurationChanges::create());
        OUString sCurCertMgr = m_xParameterEdit->get_text();
        officecfg::Office::Common::Security::Scripting::CertMgrPath::set(sCurCertMgr, pBatch);
        pBatch->commit();
    }
    catch (const uno::Exception&)
    {
        TOOLS_WARN_EXCEPTION("cui.options", "CertMgrPBHdl");
    }
}

SvxSecurityTabPage::~SvxSecurityTabPage()
{
}
@@ -750,6 +788,17 @@ void SvxSecurityTabPage::InitControls()
    {
        m_xSavePasswordsCB->set_sensitive( false );
    }

    try
    {
        OUString sCurCertMgr = officecfg::Office::Common::Security::Scripting::CertMgrPath::get();

        if (!sCurCertMgr.isEmpty())
            m_xParameterEdit->set_text(sCurCertMgr);
    }
    catch (const uno::Exception&)
    {
    }
}

std::unique_ptr<SfxTabPage> SvxSecurityTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet )
@@ -803,6 +852,15 @@ bool SvxSecurityTabPage::FillItemSet( SfxItemSet* )
        CheckAndSave( SvtSecurityOptions::EOption::BlockUntrustedRefererLinks, m_xSecOptDlg->IsBlockUntrustedRefererLinksChecked(), bModified );
    }

    std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
        comphelper::ConfigurationChanges::create());
    if (m_xParameterEdit->get_value_changed_from_saved())
    {
        OUString sCurCertMgr = m_xParameterEdit->get_text();
        officecfg::Office::Common::Security::Scripting::CertMgrPath::set(sCurCertMgr, pBatch);
        pBatch->commit();
    }

    return bModified;
}

diff --git a/cui/source/options/optinet2.hxx b/cui/source/options/optinet2.hxx
index 4d03d2d..9fea649 100644
--- a/cui/source/options/optinet2.hxx
+++ b/cui/source/options/optinet2.hxx
@@ -104,6 +104,9 @@ private:

    std::unique_ptr<weld::Label> m_xNoPasswordSaveFT;

    std::unique_ptr<weld::Button> m_xCertMgrPathLB;
    std::unique_ptr<weld::Entry> m_xParameterEdit;

    DECL_LINK(SecurityOptionsHdl, weld::Button&, void);
    DECL_LINK(SavePasswordHdl, weld::Toggleable&, void);
    DECL_LINK(MasterPasswordHdl, weld::Button&, void);
@@ -112,6 +115,7 @@ private:
    DECL_LINK(MacroSecPBHdl, weld::Button&, void );
    DECL_LINK(CertPathPBHdl, weld::Button&, void );
    DECL_LINK(TSAURLsPBHdl, weld::Button&, void );
    DECL_LINK(CertMgrPBHdl, weld::Button&, void );

    void                InitControls();

diff --git a/cui/uiconfig/ui/optsecuritypage.ui b/cui/uiconfig/ui/optsecuritypage.ui
index c728259..0c6099e 100644
--- a/cui/uiconfig/ui/optsecuritypage.ui
+++ b/cui/uiconfig/ui/optsecuritypage.ui
@@ -1,53 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<!-- Generated with glade 3.40.0 -->
<interface domain="cui">
  <requires lib="gtk+" version="3.20"/>
  <!-- n-columns=1 n-rows=1 -->
  <!-- n-columns=1 n-rows=6 -->
  <object class="GtkGrid" id="OptSecurityPage">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="border_width">6</property>
    <property name="row_spacing">12</property>
    <property name="can-focus">False</property>
    <property name="border-width">6</property>
    <property name="row-spacing">12</property>
    <child>
      <object class="GtkFrame" id="tsaurls">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="can-focus">False</property>
        <property name="hexpand">True</property>
        <property name="label_xalign">0</property>
        <property name="shadow_type">none</property>
        <property name="label-xalign">0</property>
        <property name="shadow-type">none</property>
        <child>
          <!-- n-columns=1 n-rows=1 -->
          <!-- n-columns=2 n-rows=1 -->
          <object class="GtkGrid" id="grid8">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="hexpand">True</property>
            <property name="column_spacing">24</property>
            <property name="can-focus">False</property>
            <property name="margin-start">12</property>
            <property name="margin-top">6</property>
            <property name="hexpand">True</property>
            <property name="column-spacing">24</property>
            <child>
              <object class="GtkLabel" id="label9">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="can-focus">False</property>
                <property name="hexpand">True</property>
                <property name="label" translatable="yes" context="optsecuritypage|label9">Maintain a list of Time Stamping Authority (TSA) URLs to be used for digital signatures in PDF export.</property>
                <property name="wrap">True</property>
                <property name="width_chars">56</property>
                <property name="max_width_chars">56</property>
                <property name="width-chars">56</property>
                <property name="max-width-chars">56</property>
                <property name="xalign">0</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
                <property name="left-attach">0</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="tsas">
                <property name="label" translatable="yes" context="optsecuritypage|tsas">_TSAs...</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="valign">center</property>
                <property name="use_underline">True</property>
                <property name="use-underline">True</property>
                <child internal-child="accessible">
                  <object class="AtkObject" id="tsas-atkobject">
                    <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|tsas">Opens the Time Stamping Authority URLs dialog.</property>
@@ -55,8 +55,8 @@
                </child>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
                <property name="left-attach">1</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
          </object>
@@ -64,7 +64,7 @@
        <child type="label">
          <object class="GtkLabel" id="label10">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="can-focus">False</property>
            <property name="label" translatable="yes" context="optsecuritypage|label10">TSAs</property>
            <attributes>
              <attribute name="weight" value="bold"/>
@@ -73,50 +73,50 @@
        </child>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">4</property>
        <property name="left-attach">0</property>
        <property name="top-attach">4</property>
      </packing>
    </child>
    <child>
      <object class="GtkFrame" id="certificatepath">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="can-focus">False</property>
        <property name="hexpand">True</property>
        <property name="label_xalign">0</property>
        <property name="shadow_type">none</property>
        <property name="label-xalign">0</property>
        <property name="shadow-type">none</property>
        <child>
          <!-- n-columns=1 n-rows=1 -->
          <!-- n-columns=2 n-rows=1 -->
          <object class="GtkGrid" id="grid7">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="hexpand">True</property>
            <property name="column_spacing">24</property>
            <property name="can-focus">False</property>
            <property name="margin-start">12</property>
            <property name="margin-top">6</property>
            <property name="hexpand">True</property>
            <property name="column-spacing">24</property>
            <child>
              <object class="GtkLabel" id="label7">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="can-focus">False</property>
                <property name="hexpand">True</property>
                <property name="label" translatable="yes" context="optsecuritypage|label7">Select the Network Security Services certificate directory to use for digital signatures.</property>
                <property name="wrap">True</property>
                <property name="width_chars">56</property>
                <property name="max_width_chars">56</property>
                <property name="width-chars">56</property>
                <property name="max-width-chars">56</property>
                <property name="xalign">0</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
                <property name="left-attach">0</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="cert">
                <property name="label" translatable="yes" context="optsecuritypage|cert">_Certificate...</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="valign">center</property>
                <property name="use_underline">True</property>
                <property name="use-underline">True</property>
                <child internal-child="accessible">
                  <object class="AtkObject" id="cert-atkobject">
                    <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|cert">Opens the Certificate Path dialog.</property>
@@ -124,8 +124,8 @@
                </child>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
                <property name="left-attach">1</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
          </object>
@@ -133,7 +133,7 @@
        <child type="label">
          <object class="GtkLabel" id="label8">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="can-focus">False</property>
            <property name="label" translatable="yes" context="optsecuritypage|label8">Certificate Path</property>
            <attributes>
              <attribute name="weight" value="bold"/>
@@ -142,50 +142,50 @@
        </child>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">3</property>
        <property name="left-attach">0</property>
        <property name="top-attach">3</property>
      </packing>
    </child>
    <child>
      <object class="GtkFrame" id="macrosecurity">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="can-focus">False</property>
        <property name="hexpand">True</property>
        <property name="label_xalign">0</property>
        <property name="shadow_type">none</property>
        <property name="label-xalign">0</property>
        <property name="shadow-type">none</property>
        <child>
          <!-- n-columns=1 n-rows=1 -->
          <!-- n-columns=2 n-rows=1 -->
          <object class="GtkGrid" id="grid3">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="hexpand">True</property>
            <property name="column_spacing">24</property>
            <property name="can-focus">False</property>
            <property name="margin-start">12</property>
            <property name="margin-top">6</property>
            <property name="hexpand">True</property>
            <property name="column-spacing">24</property>
            <child>
              <object class="GtkLabel" id="label5">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="can-focus">False</property>
                <property name="hexpand">True</property>
                <property name="label" translatable="yes" context="optsecuritypage|label5">Adjust the security level for executing macros and specify trusted macro developers.</property>
                <property name="wrap">True</property>
                <property name="width_chars">56</property>
                <property name="max_width_chars">56</property>
                <property name="width-chars">56</property>
                <property name="max-width-chars">56</property>
                <property name="xalign">0</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
                <property name="left-attach">0</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="macro">
                <property name="label" translatable="yes" context="optsecuritypage|macro">Macro Securit_y...</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="valign">center</property>
                <property name="use_underline">True</property>
                <property name="use-underline">True</property>
                <child internal-child="accessible">
                  <object class="AtkObject" id="macro-atkobject">
                    <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|macro">Opens the Macro Security dialog.</property>
@@ -193,8 +193,8 @@
                </child>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
                <property name="left-attach">1</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
          </object>
@@ -202,7 +202,7 @@
        <child type="label">
          <object class="GtkLabel" id="label3">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="can-focus">False</property>
            <property name="label" translatable="yes" context="optsecuritypage|label3">Macro Security</property>
            <attributes>
              <attribute name="weight" value="bold"/>
@@ -211,41 +211,41 @@
        </child>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">2</property>
        <property name="left-attach">0</property>
        <property name="top-attach">2</property>
      </packing>
    </child>
    <child>
      <object class="GtkFrame" id="frame2">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="can-focus">False</property>
        <property name="hexpand">True</property>
        <property name="label_xalign">0</property>
        <property name="shadow_type">none</property>
        <property name="label-xalign">0</property>
        <property name="shadow-type">none</property>
        <child>
          <!-- n-columns=1 n-rows=1 -->
          <!-- n-columns=2 n-rows=1 -->
          <object class="GtkGrid" id="grid2">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="hexpand">True</property>
            <property name="column_spacing">24</property>
            <property name="can-focus">False</property>
            <property name="margin-start">12</property>
            <property name="margin-top">6</property>
            <property name="hexpand">True</property>
            <property name="column-spacing">24</property>
            <child>
              <!-- n-columns=1 n-rows=1 -->
              <!-- n-columns=1 n-rows=2 -->
              <object class="GtkGrid" id="grid4">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="can-focus">False</property>
                <property name="hexpand">True</property>
                <property name="row_spacing">12</property>
                <property name="row-spacing">12</property>
                <child>
                  <object class="GtkCheckButton" id="savepassword">
                    <property name="label" translatable="yes" context="optsecuritypage|savepassword">Persistently _save passwords for web connections</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">False</property>
                    <property name="use_underline">True</property>
                    <property name="draw_indicator">True</property>
                    <property name="can-focus">True</property>
                    <property name="receives-default">False</property>
                    <property name="use-underline">True</property>
                    <property name="draw-indicator">True</property>
                    <child internal-child="accessible">
                      <object class="AtkObject" id="savepassword-atkobject">
                        <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|savepassword">If enabled, all passwords that you use to access files from web servers will be securely stored. You can retrieve the passwords from the list after you enter the master password.</property>
@@ -253,100 +253,100 @@
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">0</property>
                    <property name="left-attach">0</property>
                    <property name="top-attach">0</property>
                  </packing>
                </child>
                <child>
                  <!-- n-columns=1 n-rows=1 -->
                  <!-- n-columns=1 n-rows=3 -->
                  <object class="GtkGrid" id="grid5">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="hexpand">True</property>
                    <property name="row_spacing">6</property>
                    <property name="can-focus">False</property>
                    <property name="margin-start">12</property>
                    <property name="hexpand">True</property>
                    <property name="row-spacing">6</property>
                    <child>
                      <object class="GtkCheckButton" id="usemasterpassword">
                        <property name="label" translatable="yes" context="optsecuritypage|usemasterpassword">Protected _by a master password (recommended)</property>
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">False</property>
                        <property name="use_underline">True</property>
                        <property name="draw_indicator">True</property>
                        <property name="can-focus">True</property>
                        <property name="receives-default">False</property>
                        <property name="use-underline">True</property>
                        <property name="draw-indicator">True</property>
                      </object>
                      <packing>
                        <property name="left_attach">0</property>
                        <property name="top_attach">0</property>
                        <property name="left-attach">0</property>
                        <property name="top-attach">0</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkLabel" id="masterpasswordtext">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="can-focus">False</property>
                        <property name="hexpand">True</property>
                        <property name="label" translatable="yes" context="optsecuritypage|masterpasswordtext">Passwords are protected by a master password. You will be asked to enter it once per session, if %PRODUCTNAME retrieves a password from the protected password list.</property>
                        <property name="wrap">True</property>
                        <property name="width_chars">56</property>
                        <property name="max_width_chars">56</property>
                        <property name="width-chars">56</property>
                        <property name="max-width-chars">56</property>
                        <property name="xalign">0</property>
                        <attributes>
                          <attribute name="scale" value="0.9"/>
                          <attribute name="scale" value="0.90000000000000002"/>
                        </attributes>
                      </object>
                      <packing>
                        <property name="left_attach">0</property>
                        <property name="top_attach">1</property>
                        <property name="left-attach">0</property>
                        <property name="top-attach">1</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkLabel" id="nopasswordsave">
                        <property name="can_focus">False</property>
                        <property name="no_show_all">True</property>
                        <property name="can-focus">False</property>
                        <property name="no-show-all">True</property>
                        <property name="hexpand">True</property>
                        <property name="label" translatable="yes" context="optsecuritypage|nopasswordsave">Disabling the function to persistently store passwords deletes the list of passwords stored and resets the master password.

Do you want to delete password list and reset master password?</property>
                        <property name="wrap">True</property>
                        <property name="width_chars">56</property>
                        <property name="max_width_chars">56</property>
                        <property name="width-chars">56</property>
                        <property name="max-width-chars">56</property>
                        <property name="xalign">0</property>
                      </object>
                      <packing>
                        <property name="left_attach">0</property>
                        <property name="top_attach">2</property>
                        <property name="left-attach">0</property>
                        <property name="top-attach">2</property>
                      </packing>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">1</property>
                    <property name="left-attach">0</property>
                    <property name="top-attach">1</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
                <property name="left-attach">0</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
            <child>
              <!-- n-columns=1 n-rows=1 -->
              <!-- n-columns=1 n-rows=2 -->
              <object class="GtkGrid" id="grid6">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="row_homogeneous">True</property>
                <property name="can-focus">False</property>
                <property name="row-homogeneous">True</property>
                <child>
                  <!-- n-columns=1 n-rows=1 -->
                  <object class="GtkGrid" id="grid9">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="can-focus">False</property>
                    <child>
                      <object class="GtkButton" id="connections">
                        <property name="label" translatable="yes" context="optsecuritypage|connections">Connect_ions...</property>
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                        <property name="can-focus">True</property>
                        <property name="receives-default">True</property>
                        <property name="valign">center</property>
                        <property name="use_underline">True</property>
                        <property name="use-underline">True</property>
                        <child internal-child="accessible">
                          <object class="AtkObject" id="connections-atkobject">
                            <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|connections">Asks for the master password. If master password is correct, shows the Stored Web Connection Information dialog.</property>
@@ -354,29 +354,29 @@ Do you want to delete password list and reset master password?</property>
                        </child>
                      </object>
                      <packing>
                        <property name="left_attach">0</property>
                        <property name="top_attach">0</property>
                        <property name="left-attach">0</property>
                        <property name="top-attach">0</property>
                      </packing>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">0</property>
                    <property name="left-attach">0</property>
                    <property name="top-attach">0</property>
                  </packing>
                </child>
                <child>
                  <!-- n-columns=1 n-rows=1 -->
                  <object class="GtkGrid" id="grid10">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="can-focus">False</property>
                    <child>
                      <object class="GtkButton" id="masterpassword">
                        <property name="label" translatable="yes" context="optsecuritypage|masterpassword">_Master Password...</property>
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                        <property name="can-focus">True</property>
                        <property name="receives-default">True</property>
                        <property name="valign">center</property>
                        <property name="use_underline">True</property>
                        <property name="use-underline">True</property>
                        <child internal-child="accessible">
                          <object class="AtkObject" id="masterpassword-atkobject">
                            <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|masterpassword">Opens the Enter Master Password dialog.</property>
@@ -384,20 +384,20 @@ Do you want to delete password list and reset master password?</property>
                        </child>
                      </object>
                      <packing>
                        <property name="left_attach">0</property>
                        <property name="top_attach">0</property>
                        <property name="left-attach">0</property>
                        <property name="top-attach">0</property>
                      </packing>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">1</property>
                    <property name="left-attach">0</property>
                    <property name="top-attach">1</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
                <property name="left-attach">1</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
          </object>
@@ -405,7 +405,7 @@ Do you want to delete password list and reset master password?</property>
        <child type="label">
          <object class="GtkLabel" id="label2">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="can-focus">False</property>
            <property name="label" translatable="yes" context="optsecuritypage|label2">Passwords for Web Connections</property>
            <attributes>
              <attribute name="weight" value="bold"/>
@@ -414,50 +414,50 @@ Do you want to delete password list and reset master password?</property>
        </child>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">1</property>
        <property name="left-attach">0</property>
        <property name="top-attach">1</property>
      </packing>
    </child>
    <child>
      <object class="GtkFrame" id="frame1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="can-focus">False</property>
        <property name="hexpand">True</property>
        <property name="label_xalign">0</property>
        <property name="shadow_type">none</property>
        <property name="label-xalign">0</property>
        <property name="shadow-type">none</property>
        <child>
          <!-- n-columns=1 n-rows=1 -->
          <!-- n-columns=2 n-rows=1 -->
          <object class="GtkGrid" id="grid1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="hexpand">True</property>
            <property name="column_spacing">24</property>
            <property name="can-focus">False</property>
            <property name="margin-start">12</property>
            <property name="margin-top">6</property>
            <property name="hexpand">True</property>
            <property name="column-spacing">24</property>
            <child>
              <object class="GtkLabel" id="label4">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="can-focus">False</property>
                <property name="hexpand">True</property>
                <property name="label" translatable="yes" context="optsecuritypage|label4">Adjust security related options and define warnings for hidden information in documents.  </property>
                <property name="wrap">True</property>
                <property name="width_chars">56</property>
                <property name="max_width_chars">56</property>
                <property name="width-chars">56</property>
                <property name="max-width-chars">56</property>
                <property name="xalign">0</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
                <property name="left-attach">0</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="options">
                <property name="label" translatable="yes" context="optsecuritypage|options">O_ptions...</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="valign">center</property>
                <property name="use_underline">True</property>
                <property name="use-underline">True</property>
                <child internal-child="accessible">
                  <object class="AtkObject" id="options-atkobject">
                    <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|options">Opens the "Security Options and Warnings" dialog.</property>
@@ -465,8 +465,8 @@ Do you want to delete password list and reset master password?</property>
                </child>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
                <property name="left-attach">1</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
          </object>
@@ -474,7 +474,7 @@ Do you want to delete password list and reset master password?</property>
        <child type="label">
          <object class="GtkLabel" id="label1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="can-focus">False</property>
            <property name="label" translatable="yes" context="optsecuritypage|label1">Security Options and Warnings</property>
            <attributes>
              <attribute name="weight" value="bold"/>
@@ -483,14 +483,96 @@ Do you want to delete password list and reset master password?</property>
        </child>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">0</property>
        <property name="left-attach">0</property>
        <property name="top-attach">0</property>
      </packing>
    </child>
    <child internal-child="accessible">
      <object class="AtkObject" id="OptSecurityPage-atkobject">
        <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|OptSecurityPage">Defines the security options for saving documents, for web connections, and for opening documents that contain macros.</property>
    <child>
      <object class="GtkFrame" id="certmgr">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="hexpand">True</property>
        <property name="label-xalign">0</property>
        <property name="shadow-type">none</property>
        <child>
          <!-- n-columns=2 n-rows=2 -->
          <object class="GtkGrid">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="row-spacing">8</property>
            <property name="column-spacing">24</property>
            <property name="margin-start">12</property>
            <property name="margin-top">6</property>
            <child>
              <object class="GtkLabel" id="label11">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="hexpand">True</property>
                <property name="label" translatable="yes" context="optsecuritypage|label9">Select custom certificate manager executable. Note that LibreOffice tries to locate installed ones automatically.</property>
                <property name="wrap">True</property>
                <property name="width-chars">56</property>
                <property name="max-width-chars">56</property>
                <property name="xalign">0</property>
              </object>
              <packing>
                <property name="left-attach">0</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="browse">
                <property name="label" translatable="yes" context="stock1">_Browse...</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="can-default">True</property>
                <property name="has-default">True</property>
                <property name="receives-default">True</property>
                <property name="use-underline">True</property>
                <property name="image-position">right</property>
              </object>
              <packing>
                <property name="left-attach">1</property>
                <property name="top-attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="parameterfield">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="hexpand">True</property>
                <property name="activates-default">True</property>
                <property name="truncate-multiline">True</property>
                <child internal-child="accessible">
                  <object class="AtkObject" id="parameterfield-atkobject">
                    <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|parameterfield">Enter the executable of the certificate manager path.</property>
                  </object>
                </child>
              </object>
              <packing>
                <property name="left-attach">0</property>
                <property name="top-attach">1</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </object>
        </child>
        <child type="label">
          <object class="GtkLabel" id="label12">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="label" translatable="yes" context="optsecuritypage|label10">Certificate Manager</property>
            <attributes>
              <attribute name="weight" value="bold"/>
            </attributes>
          </object>
        </child>
      </object>
      <packing>
        <property name="left-attach">0</property>
        <property name="top-attach">5</property>
      </packing>
    </child>
  </object>
  <object class="GtkSizeGroup" id="sizegroup1">
@@ -501,6 +583,7 @@ Do you want to delete password list and reset master password?</property>
      <widget name="connections"/>
      <widget name="masterpassword"/>
      <widget name="options"/>
      <widget name="browse"/>
    </widgets>
  </object>
</interface>
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index 528cd5a..87ee6c6 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -2406,6 +2406,12 @@
            <desc>Contains the last path manually selected by the user for the CertDir property.</desc>
          </info>
        </prop>
        <prop oor:name="CertMgrPath" oor:type="xs:string" oor:nillable="false">
          <info>
            <desc>Contains the path of certificate manager if specified.</desc>
          </info>
          <value></value>
        </prop>
        <prop oor:name="TSAURLs" oor:type="oor:string-list">
          <info>
            <desc>Contains the URLs or Time Stamping Authority servers.</desc>
diff --git a/xmlsecurity/Module_xmlsecurity.mk b/xmlsecurity/Module_xmlsecurity.mk
index 2416d60..f5b4426 100644
--- a/xmlsecurity/Module_xmlsecurity.mk
+++ b/xmlsecurity/Module_xmlsecurity.mk
@@ -15,6 +15,10 @@ $(eval $(call gb_Module_add_targets,xmlsecurity,\
	UIConfig_xmlsec \
))

$(eval $(call gb_Library_use_custom_headers,xmlsecurity,\
    officecfg/registry \
))

$(eval $(call gb_Module_add_slowcheck_targets,xmlsecurity,\
    CppunitTest_xmlsecurity_pdfsigning \
))
diff --git a/xmlsecurity/inc/digitalsignaturesdialog.hxx b/xmlsecurity/inc/digitalsignaturesdialog.hxx
index 21b04811..09a9bd0 100644
--- a/xmlsecurity/inc/digitalsignaturesdialog.hxx
+++ b/xmlsecurity/inc/digitalsignaturesdialog.hxx
@@ -90,6 +90,8 @@ private:
    void                ImplFillSignaturesBox();
    void                ImplShowSignaturesDetails();
    bool                IsThereCertificateMgr();
    void                GetCertificateManager(OUString& aPath, OUString& sExecutable, OUString& sFoundGUIServer);
    bool                GetPathAllOS(OUString& aPath);

    css::uno::Reference<css::security::XCertificate> getCertificate(const SignatureInformation& rInfo);
    css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getSecurityEnvironmentForCertificate(
diff --git a/xmlsecurity/inc/strings.hrc b/xmlsecurity/inc/strings.hrc
index 8cf89b2..46e4c58 100644
--- a/xmlsecurity/inc/strings.hrc
+++ b/xmlsecurity/inc/strings.hrc
@@ -35,6 +35,7 @@
#define STR_THUMBPRINT_SHA1                         NC_("STR_THUMBPRINT_SHA1", "Thumbprint SHA1")
#define STR_THUMBPRINT_MD5                          NC_("STR_THUMBPRINT_MD5", "Thumbprint MD5")

#define STR_XMLSECDLG_OPENED_CRTMGR                 NC_("STR_XMLSECDLG_OPENED_CRTMGR", "You have opened the certificate manager at\n")
#define STR_XMLSECDLG_OLD_ODF_FORMAT                NC_("STR_XMLSECDLG_OLD_ODF_FORMAT", "This document contains signatures in ODF 1.1 (OpenOffice.org 2.x) format. " \
                                                       "Signing documents in %PRODUCTNAME %PRODUCTVERSION requires ODF 1.2 format version. " \
                                                       "Thus no signatures can be added or removed to this document.\n\n" \
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index 921dedb..7ce82fd 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -17,6 +17,7 @@
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <rtl/ustring.hxx>
#include <sal/config.h>

#include <string_view>
@@ -27,6 +28,8 @@
#include <biginteger.hxx>
#include <sax/tools/converter.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <comphelper/configuration.hxx>
#include <officecfg/Office/Common.hxx>

#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
@@ -116,17 +119,21 @@ namespace
        m_nODF = nTmp;
    }
#ifdef _WIN32
    constexpr std::u16string_view aGUIServers[]  = { u"Gpg4win\\kleopatra.exe",
                                                   u"Gpg4win\\bin\\kleopatra.exe",
                                                   u"GNU\\GnuPG\\kleopatra.exe",
                                                   u"GNU\\GnuPG\\launch-gpa.exe",
                                                   u"GNU\\GnuPG\\gpa.exe",
                                                   u"GnuPG\\bin\\gpa.exe",
                                                   u"GNU\\GnuPG\\bin\\kleopatra.exe",
                                                   u"GNU\\GnuPG\\bin\\launch-gpa.exe",
                                                   u"GNU\\GnuPG\\bin\\gpa.exe"};
std::vector<std::u16string_view> aGUIServers
    = { u"Gpg4win\\kleopatra.exe",
        u"Gpg4win\\bin\\kleopatra.exe",
        u"GNU\\GnuPG\\kleopatra.exe",
        u"GNU\\GnuPG\\launch-gpa.exe",
        u"GNU\\GnuPG\\gpa.exe",
        u"GnuPG\\bin\\gpa.exe",
        u"GNU\\GnuPG\\bin\\kleopatra.exe",
        u"GNU\\GnuPG\\bin\\launch-gpa.exe",
        u"GNU\\GnuPG\\bin\\gpa.exe",
        officecfg::Office::Common::Security::Scripting::CertMgrPath::get() };
#else
    constexpr std::u16string_view aGUIServers[] = { u"kleopatra", u"seahorse", u"gpa", u"kgpg" };
std::vector<std::u16string_view> aGUIServers
    = { u"kleopatra", u"seahorse", u"gpa", u"kgpg",
        officecfg::Office::Common::Security::Scripting::CertMgrPath::get() };
#endif

}
@@ -216,9 +223,9 @@ DigitalSignaturesDialog::DigitalSignaturesDialog(
        m_xStartCertMgrBtn->hide();
    }

    if ( !IsThereCertificateMgr() )
    if (!IsThereCertificateMgr())
    {
        m_xStartCertMgrBtn->hide();
        m_xStartCertMgrBtn->set_sensitive(false);
    }
}

@@ -311,23 +318,19 @@ bool DigitalSignaturesDialog::canAddRemove()
            //It the user presses 'Add' or 'Remove' several times then, then the warning
            //is shown every time until the user presses 'OK'. From then on, the warning
            //is not displayed anymore as long as the signatures dialog is alive.
            std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
                                                      VclMessageType::Question, VclButtonsType::YesNo,
                                                      XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)));
            std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
                m_xDialog.get(), VclMessageType::Question, VclButtonsType::YesNo,
                XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)));
            if (xBox->run() == RET_NO)
                ret = false;
            else
                m_bWarningShowSignMacro = true;

        }
    }
    return ret;
}

bool DigitalSignaturesDialog::canAdd()
{
    return canAddRemove();
}
bool DigitalSignaturesDialog::canAdd() { return canAddRemove(); }

bool DigitalSignaturesDialog::canRemove()
{
@@ -492,10 +495,11 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, weld::Button&, void)
    }
}

bool DigitalSignaturesDialog::IsThereCertificateMgr()
bool DigitalSignaturesDialog::GetPathAllOS(OUString& aPath)
{
#ifdef _WIN32
    static const OUString aPath = [] {
    aPath = []
    {
        sal::systools::CoTaskMemAllocated<wchar_t> sPath;
        HRESULT hr
            = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath);
@@ -509,77 +513,91 @@ bool DigitalSignaturesDialog::IsThereCertificateMgr()
    const char* cPath = getenv("PATH");
    if (!cPath)
        return false;
    OUString aPath(cPath, strlen(cPath), osl_getThreadTextEncoding());
    aPath = OUString(cPath, strlen(cPath), osl_getThreadTextEncoding());
#endif
    return (!aPath.isEmpty());
}

    OUString sFoundGUIServer, sExecutable;
void DigitalSignaturesDialog::GetCertificateManager(OUString& aPath, OUString& sExecutable,
                                            OUString& sFoundGUIServer)
{
    aGUIServers.pop_back();
    aGUIServers.push_back(officecfg::Office::Common::Security::Scripting::CertMgrPath::get());

    for ( auto const &rServer : aGUIServers )
    for (auto it = aGUIServers.rbegin(); it != aGUIServers.rend(); ++it)
    {
        osl::FileBase::RC searchError = osl::File::searchFileURL(OUString(rServer), aPath, sFoundGUIServer );
        const auto& rServer = *it;

        if (rServer.empty())
            continue;

        bool bValidSetMgr = (it == aGUIServers.rbegin() && rServer.size() > 0);
        sal_Int32 nLastBackslashIndex = -1;

        if (bValidSetMgr)
        {
#ifdef _WIN32
            nLastBackslashIndex = rServer.find_last_of('\\');
#else
            nLastBackslashIndex = rServer.find_last_of('/');
#endif
        }

        osl::FileBase::RC searchError = osl::File::searchFileURL(
            OUString(bValidSetMgr ? rServer.substr(nLastBackslashIndex + 1) : rServer), aPath,
            sFoundGUIServer);
        if (searchError == osl::FileBase::E_None)
        {
            osl::File::getSystemPathFromFileURL( sFoundGUIServer, sExecutable );
            osl::File::getSystemPathFromFileURL(sFoundGUIServer, sExecutable);
            if (it != aGUIServers.rbegin())
            {
                std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
                    comphelper::ConfigurationChanges::create());
                officecfg::Office::Common::Security::Scripting::CertMgrPath::set(sExecutable,
                                                                                 pBatch);
                pBatch->commit();
            }

            break;
        }
    }
}

    return ( !sExecutable.isEmpty() );
bool DigitalSignaturesDialog::IsThereCertificateMgr()
{
    OUString aPath, sFoundGUIServer, sExecutable;
    if (!GetPathAllOS(aPath))
        return false;
    GetCertificateManager(aPath, sExecutable, sFoundGUIServer);
    return (!sExecutable.isEmpty());
}

IMPL_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, weld::Button&, void)
{
#ifdef _WIN32
    // FIXME: call GpgME::dirInfo("bindir") somewhere in
    // SecurityEnvironmentGpg or whatnot
    // FIXME: perhaps poke GpgME for uiserver, and hope it returns something useful?
    static const OUString aPath = [] {
        sal::systools::CoTaskMemAllocated<wchar_t> sPath;
        HRESULT hr
            = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath);
        if (SUCCEEDED(hr))
            return OUString(o3tl::toU(sPath));
        return OUString();
    }();
    if (aPath.isEmpty())
    OUString aPath, sFoundGUIServer, sExecutable;
    if (!GetPathAllOS(aPath))
        return;
#else
    const char* cPath = getenv("PATH");
    if (!cPath)
        return;
    OUString aPath(cPath, strlen(cPath), osl_getThreadTextEncoding());
#endif

    OUString sFoundGUIServer, sExecutable;
    GetCertificateManager(aPath, sExecutable, sFoundGUIServer);

    for ( auto const &rServer : aGUIServers)
    if (!sExecutable.isEmpty())
    {
        osl::FileBase::RC searchError = osl::File::searchFileURL(OUString(rServer), aPath, sFoundGUIServer );
        if (searchError == osl::FileBase::E_None)
        {
            osl::File::getSystemPathFromFileURL( sFoundGUIServer, sExecutable );
            break;
        }
        uno::Reference<uno::XComponentContext> xContext
            = ::comphelper::getProcessComponentContext();
        uno::Reference<css::system::XSystemShellExecute> xSystemShell(
            css::system::SystemShellExecute::create(xContext));

        xSystemShell->execute(sExecutable, OUString(),
                              css::system::SystemShellExecuteFlags::DEFAULTS);
    }

    if ( !sExecutable.isEmpty() )
    {
        uno::Reference< uno::XComponentContext > xContext =
            ::comphelper::getProcessComponentContext();
        uno::Reference< css::system::XSystemShellExecute > xSystemShell(
                 css::system::SystemShellExecute::create(xContext) );
    OUString sDialogText = (sExecutable.isEmpty() ?
        XsResId(STR_XMLSECDLG_NO_CERT_MANAGER) : XsResId(STR_XMLSECDLG_OPENED_CRTMGR) + sExecutable);

        xSystemShell->execute( sExecutable, OUString(),
            css::system::SystemShellExecuteFlags::DEFAULTS );
    }
    else
    {
        std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
                                                      VclMessageType::Info, VclButtonsType::Ok,
                                                      XsResId(STR_XMLSECDLG_NO_CERT_MANAGER)));
        xInfoBox->run();
    }
    std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(
        m_xDialog.get(), VclMessageType::Info, VclButtonsType::Ok,
        sDialogText));
    xInfoBox->run();
}

IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl, LinkParamNone*, bool)