cool#10630 doc electronic sign: fix insertion of the signature line
Have electronic signing configured in the LOK client, try to insert a signature line, you'll get a certificate picker, while we don't have a cert during esign. What's in fact needed for creating the signature line is just a name (previously extracted from the certificate), we can survive the lack of actual certificate. Fix the problem by adding a new External parameter to .uno:InsertSignatureLine to hint that the certificate chooser should not be opened, instead the editor name (used for comments already) should be used. Add a new CertificateOrName in svl/ and use that in all places where previously we wanted a certificate but in fact it's enough to have a certificate or a name to create the signature line. The name on the signature line is just visual feedback, the actual name on the crypto signature is still not based on untrusted used input. Change-Id: Ib7008112a8e28a9e7d9649745e6021dd6b6b9c39 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180193 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
This commit is contained in:
@@ -163,8 +163,10 @@ IMPL_LINK_NOARG(SignSignatureLineDialog, chooseCertificate, weld::Button&, void)
|
||||
if (xSignCertificate.is())
|
||||
{
|
||||
m_xSelectedCertifate = xSignCertificate;
|
||||
svl::crypto::CertificateOrName aCertificateOrName;
|
||||
aCertificateOrName.m_xCertificate = xSignCertificate;
|
||||
m_xBtnChooseCertificate->set_label(
|
||||
svx::SignatureLineHelper::getSignerName(xSignCertificate));
|
||||
svx::SignatureLineHelper::getSignerName(aCertificateOrName));
|
||||
}
|
||||
ValidateFields();
|
||||
}
|
||||
@@ -210,9 +212,11 @@ css::uno::Reference<css::graphic::XGraphic> SignSignatureLineDialog::getSignedGr
|
||||
aSvgImage = aSvgImage.replaceAll("[SIGNER_NAME]", getCDataString(m_aSuggestedSignerName));
|
||||
aSvgImage = aSvgImage.replaceAll("[SIGNER_TITLE]", getCDataString(m_aSuggestedSignerTitle));
|
||||
|
||||
svl::crypto::CertificateOrName aCertificateOrName;
|
||||
aCertificateOrName.m_xCertificate = m_xSelectedCertifate;
|
||||
OUString aIssuerLine
|
||||
= CuiResId(RID_CUISTR_SIGNATURELINE_SIGNED_BY)
|
||||
.replaceFirst("%1", svx::SignatureLineHelper::getSignerName(m_xSelectedCertifate));
|
||||
.replaceFirst("%1", svx::SignatureLineHelper::getSignerName(aCertificateOrName));
|
||||
aSvgImage = aSvgImage.replaceAll("[SIGNED_BY]", getCDataString(aIssuerLine));
|
||||
if (bValid)
|
||||
aSvgImage = aSvgImage.replaceAll("[INVALID_SIGNATURE]", "");
|
||||
|
||||
@@ -4744,7 +4744,9 @@ static void doc_initializeForRendering(LibreOfficeKitDocument* pThis,
|
||||
uno::Reference<security::XCertificate> xCertificate = SfxLokHelper::getSigningCertificate(aSignatureCert, aSignatureKey);
|
||||
if (SfxViewShell* pViewShell = SfxViewShell::Current())
|
||||
{
|
||||
pViewShell->SetSigningCertificate(xCertificate);
|
||||
svl::crypto::CertificateOrName aCertificateOrName;
|
||||
aCertificateOrName.m_xCertificate = xCertificate;
|
||||
pViewShell->SetSigningCertificate(aCertificateOrName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ namespace com::sun::star::ui { struct ContextMenuExecuteEvent; }
|
||||
namespace com::sun::star::view { class XRenderable; }
|
||||
namespace com::sun::star::security { class XCertificate; }
|
||||
namespace svtools { enum ColorConfigEntry : int; }
|
||||
namespace svl::crypto { class CertificateOrName; }
|
||||
|
||||
enum class SfxPrinterChangeFlags
|
||||
{
|
||||
@@ -492,8 +493,8 @@ public:
|
||||
|
||||
OUString getA11yFocusedParagraph() const;
|
||||
int getA11yCaretPosition() const;
|
||||
void SetSigningCertificate(const css::uno::Reference<css::security::XCertificate>& xCertificate);
|
||||
const css::uno::Reference<css::security::XCertificate> & GetSigningCertificate() const;
|
||||
void SetSigningCertificate(const svl::crypto::CertificateOrName& rCertificateOrName);
|
||||
svl::crypto::CertificateOrName GetSigningCertificate() const;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_SFX2_VIEWSH_HXX
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sal/types.h>
|
||||
|
||||
#include <utility>
|
||||
@@ -116,6 +118,17 @@ public:
|
||||
std::vector<unsigned char> m_aSignatureValue;
|
||||
};
|
||||
|
||||
/// Used for visual signing: an XCertificate or a signer name.
|
||||
class SVL_DLLPUBLIC CertificateOrName
|
||||
{
|
||||
public:
|
||||
/// If set, the certificate used for signing.
|
||||
css::uno::Reference<css::security::XCertificate> m_xCertificate;
|
||||
/// Otherwise we don't have a certificate but have a name to be featured on the visual
|
||||
/// signature.
|
||||
OUString m_aName;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <rtl/ustring.hxx>
|
||||
#include <svx/svxdllapi.h>
|
||||
#include <svl/cryptosign.hxx>
|
||||
|
||||
#include <com/sun/star/graphic/XGraphic.hpp>
|
||||
#include <com/sun/star/security/XCertificate.hpp>
|
||||
@@ -45,8 +46,7 @@ getSignatureCertificate(SfxObjectShell* pShell, SfxViewShell* pViewShell, weld::
|
||||
/**
|
||||
* Get a signer name out of a certificate.
|
||||
*/
|
||||
SVX_DLLPUBLIC OUString
|
||||
getSignerName(const css::uno::Reference<css::security::XCertificate>& xCertificate);
|
||||
SVX_DLLPUBLIC OUString getSignerName(const svl::crypto::CertificateOrName& rCertificateOrName);
|
||||
|
||||
/**
|
||||
* Gets a localized date string.
|
||||
@@ -61,9 +61,8 @@ SVX_DLLPUBLIC css::uno::Reference<css::graphic::XGraphic> importSVG(std::u16stri
|
||||
/**
|
||||
* Sets xCertificate as the signing certificate of the selected shape on pView.
|
||||
*/
|
||||
SVX_DLLPUBLIC void
|
||||
setShapeCertificate(const SdrView* pView,
|
||||
const css::uno::Reference<css::security::XCertificate>& xCertificate);
|
||||
SVX_DLLPUBLIC void setShapeCertificate(const SdrView* pView,
|
||||
const svl::crypto::CertificateOrName& rCertificateOrName);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
@@ -11,6 +11,11 @@
|
||||
|
||||
#include <sfx2/sidebar/Sidebar.hxx>
|
||||
#include <vcl/scheduler.hxx>
|
||||
#include <comphelper/propertyvalue.hxx>
|
||||
#include <comphelper/sequenceashashmap.hxx>
|
||||
|
||||
#include <DrawDocShell.hxx>
|
||||
#include <ViewShell.hxx>
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSidebarSwitchDeck)
|
||||
{
|
||||
@@ -36,6 +41,33 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSidebarSwitchDeck)
|
||||
CPPUNIT_ASSERT(it != aView.m_aStateChanges.end());
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testInsertSignatureLineExternal)
|
||||
{
|
||||
// Given a PDF to be signed:
|
||||
uno::Sequence<beans::PropertyValue> aArgs = { comphelper::makePropertyValue("ReadOnly", true) };
|
||||
loadWithParams(createFileURL(u"empty.pdf"), aArgs);
|
||||
SdXImpressDocument* pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
|
||||
sd::ViewShell* pViewShell = pImpressDocument->GetDocShell()->GetViewShell();
|
||||
sd::View* pView = pViewShell->GetView();
|
||||
pView->SetAuthor("myauthor");
|
||||
|
||||
// When insrerting a signature line for electronic (extrenal) signing:
|
||||
aArgs = {
|
||||
comphelper::makePropertyValue("External", true),
|
||||
};
|
||||
// Without the accompanying fix in place, this test would hang here in the certificate chooser
|
||||
// dialog.
|
||||
dispatchCommand(mxComponent, ".uno:InsertSignatureLine", aArgs);
|
||||
|
||||
// Then make sure the shape is marked as a signature line:
|
||||
std::vector<SdrObject*> aMarkedObjects = pView->GetMarkedObjects();
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMarkedObjects.size());
|
||||
uno::Any aAny;
|
||||
aMarkedObjects[0]->GetGrabBagItem(aAny);
|
||||
comphelper::SequenceAsHashMap aMap(aAny);
|
||||
CPPUNIT_ASSERT(aMap.contains("SignatureCertificate"));
|
||||
}
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -512,16 +512,19 @@ void FuConstructRectangle::Deactivate()
|
||||
return;
|
||||
}
|
||||
|
||||
uno::Reference<security::XCertificate> xCertificate
|
||||
= svx::SignatureLineHelper::getSignatureCertificate(mpViewShell->GetObjectShell(),
|
||||
mpViewShell->GetViewShell(),
|
||||
mpViewShell->GetFrameWeld());
|
||||
if (!xCertificate.is())
|
||||
svl::crypto::CertificateOrName aCertificateOrName = mpViewShell->GetViewShell()->GetSigningCertificate();
|
||||
if (aCertificateOrName.m_aName.isEmpty())
|
||||
{
|
||||
return;
|
||||
aCertificateOrName.m_xCertificate = svx::SignatureLineHelper::getSignatureCertificate(
|
||||
mpViewShell->GetObjectShell(), mpViewShell->GetViewShell(),
|
||||
mpViewShell->GetFrameWeld());
|
||||
if (!aCertificateOrName.m_xCertificate.is())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
svx::SignatureLineHelper::setShapeCertificate(mpView, xCertificate);
|
||||
svx::SignatureLineHelper::setShapeCertificate(mpView, aCertificateOrName);
|
||||
|
||||
// Update infobar to offer "finish signing".
|
||||
SfxViewFrame* pFrame = mpViewShell->GetViewFrame();
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include <sfx2/docfile.hxx>
|
||||
#include <sfx2/notebookbar/SfxNotebookBar.hxx>
|
||||
#include <osl/diagnose.h>
|
||||
#include <svl/cryptosign.hxx>
|
||||
|
||||
#include <DrawViewShell.hxx>
|
||||
#include <slideshow.hxx>
|
||||
@@ -471,18 +472,28 @@ void DrawViewShell::FuPermanent(SfxRequest& rReq)
|
||||
{
|
||||
aSignatureKey = pSignatureKey->GetValue().toUtf8();
|
||||
}
|
||||
bool bExternal = false;
|
||||
const SfxBoolItem* pExternal = rReq.GetArg<SfxBoolItem>(FN_PARAM_3);
|
||||
if (pExternal)
|
||||
{
|
||||
bExternal = pExternal->GetValue();
|
||||
}
|
||||
|
||||
SfxViewFrame* pFrame = GetFrame();
|
||||
SfxViewShell* pViewShell = pFrame ? pFrame->GetViewShell() : nullptr;
|
||||
if (pViewShell)
|
||||
{
|
||||
uno::Reference<security::XCertificate> xSigningCertificate;
|
||||
svl::crypto::CertificateOrName aCertificateOrName;
|
||||
if (!aSignatureCert.empty() && !aSignatureKey.empty())
|
||||
{
|
||||
xSigningCertificate = SfxLokHelper::getSigningCertificate(aSignatureCert, aSignatureKey);
|
||||
aCertificateOrName.m_xCertificate = SfxLokHelper::getSigningCertificate(aSignatureCert, aSignatureKey);
|
||||
}
|
||||
else if (bExternal)
|
||||
{
|
||||
aCertificateOrName.m_aName = mpDrawView->GetAuthor();
|
||||
}
|
||||
// Always set the signing certificate, to clear data from a previous dispatch.
|
||||
pViewShell->SetSigningCertificate(xSigningCertificate);
|
||||
pViewShell->SetSigningCertificate(aCertificateOrName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -665,13 +665,13 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
|
||||
SfxViewShell* pViewShell = pFrame ? pFrame->GetViewShell() : nullptr;
|
||||
if (pViewShell)
|
||||
{
|
||||
uno::Reference<security::XCertificate> xSigningCertificate;
|
||||
svl::crypto::CertificateOrName aCertificateOrName;
|
||||
if (!aSignatureCert.empty() && !aSignatureKey.empty())
|
||||
{
|
||||
xSigningCertificate = SfxLokHelper::getSigningCertificate(aSignatureCert, aSignatureKey);
|
||||
aCertificateOrName.m_xCertificate = SfxLokHelper::getSigningCertificate(aSignatureCert, aSignatureKey);
|
||||
}
|
||||
// Always set the signing certificate, to clear data from a previous dispatch.
|
||||
pViewShell->SetSigningCertificate(xSigningCertificate);
|
||||
pViewShell->SetSigningCertificate(aCertificateOrName);
|
||||
}
|
||||
|
||||
// Async, all code before return has to go into the callback.
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <svtools/acceleratorexecute.hxx>
|
||||
#include <rtl/ref.hxx>
|
||||
#include <vcl/print.hxx>
|
||||
#include <svl/cryptosign.hxx>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
|
||||
@@ -59,7 +60,7 @@ struct SfxViewShell_Impl
|
||||
static sal_uInt32 m_nLastViewShellId;
|
||||
const ViewShellId m_nViewShellId;
|
||||
const ViewShellDocId m_nDocId;
|
||||
css::uno::Reference<css::security::XCertificate> m_xSigningCertificate;
|
||||
svl::crypto::CertificateOrName m_aSigningCertificate;
|
||||
|
||||
explicit SfxViewShell_Impl(SfxViewShellFlags const nFlags, ViewShellDocId nDocId);
|
||||
~SfxViewShell_Impl();
|
||||
|
||||
@@ -2807,14 +2807,14 @@ int SfxViewShell::getA11yCaretPosition() const
|
||||
return rDocFocusListener.getCaretPosition();
|
||||
}
|
||||
|
||||
void SfxViewShell::SetSigningCertificate(const uno::Reference<security::XCertificate>& xCertificate)
|
||||
void SfxViewShell::SetSigningCertificate(const svl::crypto::CertificateOrName& rCertificate)
|
||||
{
|
||||
pImpl->m_xSigningCertificate = xCertificate;
|
||||
pImpl->m_aSigningCertificate = rCertificate;
|
||||
}
|
||||
|
||||
const uno::Reference<security::XCertificate> & SfxViewShell::GetSigningCertificate() const
|
||||
svl::crypto::CertificateOrName SfxViewShell::GetSigningCertificate() const
|
||||
{
|
||||
return pImpl->m_xSigningCertificate;
|
||||
return pImpl->m_aSigningCertificate;
|
||||
}
|
||||
|
||||
bool SfxViewShell::PrepareClose
|
||||
|
||||
@@ -863,7 +863,9 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testVisualSignResize)
|
||||
return;
|
||||
}
|
||||
SdrView* pView = SfxViewShell::Current()->GetDrawView();
|
||||
svx::SignatureLineHelper::setShapeCertificate(pView, xCert);
|
||||
svl::crypto::CertificateOrName aCertificateOrName;
|
||||
aCertificateOrName.m_xCertificate = xCert;
|
||||
svx::SignatureLineHelper::setShapeCertificate(pView, aCertificateOrName);
|
||||
pObjectShell->SetModified(false);
|
||||
|
||||
// When resizing the shape by moving the bottom right (last) handle towards top right:
|
||||
|
||||
+1
-1
@@ -12416,7 +12416,7 @@ SfxVoidItem AnchorMenu SID_ANCHOR_MENU
|
||||
]
|
||||
|
||||
SfxVoidItem InsertSignatureLine SID_INSERT_SIGNATURELINE
|
||||
(SfxStringItem SignatureCert FN_PARAM_1, SfxStringItem SignatureKey FN_PARAM_2)
|
||||
(SfxStringItem SignatureCert FN_PARAM_1, SfxStringItem SignatureKey FN_PARAM_2, SfxBoolItem External FN_PARAM_3)
|
||||
[
|
||||
AutoUpdate = FALSE,
|
||||
FastCall = FALSE,
|
||||
|
||||
@@ -99,10 +99,16 @@ getSignatureCertificate(SfxObjectShell* pShell, SfxViewShell* pViewShell, weld::
|
||||
return xSignCertificate;
|
||||
}
|
||||
|
||||
OUString getSignerName(const css::uno::Reference<css::security::XCertificate>& xCertificate)
|
||||
OUString getSignerName(const svl::crypto::CertificateOrName& rCertificateOrName)
|
||||
{
|
||||
return comphelper::xmlsec::GetContentPart(xCertificate->getSubjectName(),
|
||||
xCertificate->getCertificateKind());
|
||||
if (rCertificateOrName.m_xCertificate.is())
|
||||
{
|
||||
return comphelper::xmlsec::GetContentPart(
|
||||
rCertificateOrName.m_xCertificate->getSubjectName(),
|
||||
rCertificateOrName.m_xCertificate->getCertificateKind());
|
||||
}
|
||||
|
||||
return rCertificateOrName.m_aName;
|
||||
}
|
||||
|
||||
OUString getLocalizedDate()
|
||||
@@ -130,7 +136,7 @@ uno::Reference<graphic::XGraphic> importSVG(std::u16string_view rSVG)
|
||||
}
|
||||
|
||||
void setShapeCertificate(const SdrView* pView,
|
||||
const css::uno::Reference<css::security::XCertificate>& xCertificate)
|
||||
const svl::crypto::CertificateOrName& rCertificateOrName)
|
||||
{
|
||||
const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
|
||||
if (rMarkList.GetMarkCount() < 1)
|
||||
@@ -149,15 +155,21 @@ void setShapeCertificate(const SdrView* pView,
|
||||
uno::Reference<drawing::XShape> xShape = pSignatureLine->getUnoShape();
|
||||
uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
|
||||
comphelper::SequenceAsHashMap aMap(xShapeProps->getPropertyValue(u"InteropGrabBag"_ustr));
|
||||
aMap[u"SignatureCertificate"_ustr] <<= xCertificate;
|
||||
xShapeProps->setPropertyValue(u"InteropGrabBag"_ustr,
|
||||
uno::Any(aMap.getAsConstPropertyValueList()));
|
||||
if (rCertificateOrName.m_xCertificate.is())
|
||||
{
|
||||
aMap[u"SignatureCertificate"_ustr] <<= rCertificateOrName.m_xCertificate;
|
||||
}
|
||||
else
|
||||
{
|
||||
aMap[u"SignatureCertificate"_ustr] <<= rCertificateOrName.m_aName;
|
||||
}
|
||||
xShapeProps->setPropertyValue("InteropGrabBag", uno::Any(aMap.getAsConstPropertyValueList()));
|
||||
|
||||
// Read svg and replace placeholder texts.
|
||||
OUString aSvgImage(
|
||||
svx::SignatureLineHelper::getSignatureImage(u"signature-line-draw.svg"_ustr));
|
||||
aSvgImage = aSvgImage.replaceAll("[SIGNED_BY]", SvxResId(RID_SVXSTR_SIGNATURELINE_DSIGNED_BY));
|
||||
OUString aSignerName = svx::SignatureLineHelper::getSignerName(xCertificate);
|
||||
OUString aSignerName = svx::SignatureLineHelper::getSignerName(rCertificateOrName);
|
||||
aSvgImage = aSvgImage.replaceAll("[SIGNER_NAME]", aSignerName);
|
||||
OUString aDate = svx::SignatureLineHelper::getLocalizedDate();
|
||||
aDate = SvxResId(RID_SVXSTR_SIGNATURELINE_DATE).replaceFirst("%1", aDate);
|
||||
|
||||
@@ -103,7 +103,9 @@ CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testPDFAddVisibleSignatureLastPage)
|
||||
SfxViewShell* pCurrent = SfxViewShell::Current();
|
||||
CPPUNIT_ASSERT(pCurrent);
|
||||
SdrView* pView = pCurrent->GetDrawView();
|
||||
svx::SignatureLineHelper::setShapeCertificate(pView, xCert);
|
||||
svl::crypto::CertificateOrName aCertificateOrName;
|
||||
aCertificateOrName.m_xCertificate = xCert;
|
||||
svx::SignatureLineHelper::setShapeCertificate(pView, aCertificateOrName);
|
||||
|
||||
// the document is modified now, but Sign function can't show SaveAs dialog
|
||||
// in unit test, so just clear the modified
|
||||
|
||||
@@ -774,7 +774,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testPDFAddVisibleSignature)
|
||||
SfxViewShell* pCurrent = SfxViewShell::Current();
|
||||
CPPUNIT_ASSERT(pCurrent);
|
||||
SdrView* pView = pCurrent->GetDrawView();
|
||||
svx::SignatureLineHelper::setShapeCertificate(pView, xCert);
|
||||
svl::crypto::CertificateOrName aCertificateOrName;
|
||||
aCertificateOrName.m_xCertificate = xCert;
|
||||
svx::SignatureLineHelper::setShapeCertificate(pView, aCertificateOrName);
|
||||
|
||||
// the document is modified now, but Sign function can't show SaveAs dialog
|
||||
// in unit test, so just clear the modified
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <comphelper/xmlsechelper.hxx>
|
||||
#include <comphelper/lok.hxx>
|
||||
#include <sfx2/viewsh.hxx>
|
||||
#include <svl/cryptosign.hxx>
|
||||
|
||||
#include <com/sun/star/security/NoPasswordException.hpp>
|
||||
#include <com/sun/star/security/CertificateCharacters.hpp>
|
||||
@@ -227,9 +228,9 @@ void CertificateChooser::ImplInitialize(bool mbSearch)
|
||||
if (comphelper::LibreOfficeKit::isActive())
|
||||
{
|
||||
// The LOK case takes the signing certificate from the view.
|
||||
if (m_pViewShell && m_pViewShell->GetSigningCertificate().is())
|
||||
if (m_pViewShell && m_pViewShell->GetSigningCertificate().m_xCertificate.is())
|
||||
{
|
||||
xCerts = { m_pViewShell->GetSigningCertificate() };
|
||||
xCerts = { m_pViewShell->GetSigningCertificate().m_xCertificate };
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -265,7 +265,7 @@ DigitalSignaturesDialog::DigitalSignaturesDialog(
|
||||
if (comphelper::LibreOfficeKit::isActive())
|
||||
{
|
||||
// If the view has a signing certificate, then allow adding a signature.
|
||||
if (!pViewShell || !pViewShell->GetSigningCertificate().is())
|
||||
if (!pViewShell || !pViewShell->GetSigningCertificate().m_xCertificate.is())
|
||||
{
|
||||
m_xAddBtn->hide();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user