cui/source/dialogs/SignSignatureLineDialog.cxx         |    8 +
 desktop/source/lib/init.cxx                            |    7 -
 include/sfx2/objsh.hxx                                 |    6 -
 include/sfx2/viewsh.hxx                                |   11 +-
 include/svl/cryptosign.hxx                             |   16 +++
 include/svx/signaturelinehelper.hxx                    |    9 -
 sd/qa/unit/tiledrendering/data/empty.pdf               |binary
 sd/qa/unit/tiledrendering/tiledrendering2.cxx          |   56 +++++++++++
 sd/sdi/_drvwsh.sdi                                     |    1 
 sd/source/ui/func/fuconrec.cxx                         |   18 ++-
 sd/source/ui/func/fusel.cxx                            |    4 
 sd/source/ui/view/drviewse.cxx                         |   17 ++-
 sfx2/qa/cppunit/doc.cxx                                |   10 +
 sfx2/source/doc/objserv.cxx                            |   75 +-------------
 sfx2/source/view/viewfrm.cxx                           |    5 
 sfx2/source/view/viewimp.hxx                           |    3 
 sfx2/source/view/viewsh.cxx                            |   86 ++++++++++++++++-
 svl/source/crypto/cryptosign.cxx                       |    5 
 svx/qa/unit/data/empty.pdf                             |binary
 svx/qa/unit/svdraw.cxx                                 |   85 ++++++++++++++++
 svx/sdi/svx.sdi                                        |    2 
 svx/source/dialog/signaturelinehelper.cxx              |   25 ++--
 svx/source/svdraw/svddrgv.cxx                          |   12 ++
 svx/source/svdraw/svdedtv1.cxx                         |    4 
 svx/source/svdraw/svdmrkv.cxx                          |   12 ++
 vcl/qa/cppunit/filter/ipdf/ipdf.cxx                    |    5 
 xmlsecurity/qa/unit/signing/signing.cxx                |    5 
 xmlsecurity/source/dialogs/certificatechooser.cxx      |    5 
 xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx |    2 
 xmlsecurity/source/helper/pdfsignaturehelper.cxx       |   16 ---
 30 files changed, 372 insertions(+), 138 deletions(-)

New commits:
commit 3225bdeb523ab5c69448f7d32321e938208b0b21
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Jan 16 08:58:27 2025 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Feb 12 10:43:33 2025 +0100

    cool#10630 doc electronic sign: move signature line tracking to the view
    
    No functional changes intended:
    
    - Replace SfxObjectShell::GetSignPDFCertificate() and
      SfxObjectShell::ResetSignPDFCertificate() with
      SfxViewShell::SetSignPDFCertificate() and
      SfxViewShell::GetSignPDFCertificate(), because information about shape
      selection belongs to the view.
    
    - Change svx::SignatureLineHelper::setShapeCertificate() to use
      SfxViewShell::SetSignPDFCertificate() to avoid duplication.
    
    - Change GetSignatureLineShape() in xmlsecurity/ to use
      SfxViewShell::GetSignPDFCertificate(), again to avoid duplication.
    
    With this, all setters/getters of the inserted signature line go via
    SfxViewShell and the amount of getCurrentSelection() calls on the model
    is reduced.
    
    Change-Id: I021bc41262b2a16d1014fbf1431a0eb6e1e86c73
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180355
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 9fc11e799571..b686c2379e78 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -5174,8 +5174,7 @@ static bool isCommandAllowed(OUString& command) {
                 if (pViewShell && command == u".uno:TransformDialog"_ustr)
                 {
                     // If the just added signature line shape is selected, 
allow moving it.
-                    SfxObjectShell* pDocShell = pViewShell->GetObjectShell();
-                    bRet = pDocShell->GetSignPDFCertificate().Is();
+                    bRet = pViewShell->GetSignPDFCertificate().Is();
                 }
                 return bRet;
             }
diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index d97ce8e13a38..1c9281b49b87 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -813,11 +813,6 @@ public:
     /// Is this read-only object shell opened via .uno:SignPDF?
     bool IsSignPDF() const;
 
-    /// Gets the certificate that is already picked by the user but not yet 
used for signing.
-    svl::crypto::CertificateOrName GetSignPDFCertificate() const;
-
-    void ResetSignPDFCertificate();
-
     /// Gets grab-bagged password info to unprotect change tracking with 
verification
     css::uno::Sequence< css::beans::PropertyValue > 
GetDocumentProtectionFromGrabBag() const;
 
diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx
index 9d64937d6dc5..ad988db09b4c 100644
--- a/include/sfx2/viewsh.hxx
+++ b/include/sfx2/viewsh.hxx
@@ -499,6 +499,12 @@ public:
     int getA11yCaretPosition() const;
     void SetSigningCertificate(const svl::crypto::CertificateOrName& 
rCertificateOrName);
     svl::crypto::CertificateOrName GetSigningCertificate() const;
+
+    // These are used for visual signing: SetSignPDFCertificate() is called 
when the signature
+    // line is inserted, and GetSignPDFCertificate() is used by the signing 
code to get the already
+    // selected certificate.
+    void SetSignPDFCertificate(const svl::crypto::CertificateOrName& 
rCertificateOrName);
+    svl::crypto::CertificateOrName GetSignPDFCertificate() const;
 };
 
 #endif // INCLUDED_SFX2_VIEWSH_HXX
diff --git a/include/svl/cryptosign.hxx b/include/svl/cryptosign.hxx
index 25a4428ce1ad..89740a042540 100644
--- a/include/svl/cryptosign.hxx
+++ b/include/svl/cryptosign.hxx
@@ -129,7 +129,7 @@ public:
     OUString m_aName;
 
     /// Returns if a certificate or a name is set.
-    bool Is();
+    bool Is() const;
 };
 
 }
diff --git a/include/svx/signaturelinehelper.hxx 
b/include/svx/signaturelinehelper.hxx
index 6f17f3726dd2..e17d4ce148e6 100644
--- a/include/svx/signaturelinehelper.hxx
+++ b/include/svx/signaturelinehelper.hxx
@@ -61,7 +61,7 @@ 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,
+SVX_DLLPUBLIC void setShapeCertificate(SfxViewShell* pViewShell,
                                        const svl::crypto::CertificateOrName& 
rCertificateOrName);
 }
 
diff --git a/sd/source/ui/func/fuconrec.cxx b/sd/source/ui/func/fuconrec.cxx
index 2e4e7a9cfcb2..af031550258f 100644
--- a/sd/source/ui/func/fuconrec.cxx
+++ b/sd/source/ui/func/fuconrec.cxx
@@ -512,7 +512,8 @@ void FuConstructRectangle::Deactivate()
         return;
     }
 
-    svl::crypto::CertificateOrName aCertificateOrName = 
mpViewShell->GetViewShell()->GetSigningCertificate();
+    SfxViewShell* pViewShell = mpViewShell->GetViewShell();
+    svl::crypto::CertificateOrName aCertificateOrName = 
pViewShell->GetSigningCertificate();
     if (aCertificateOrName.m_aName.isEmpty())
     {
         aCertificateOrName.m_xCertificate = 
svx::SignatureLineHelper::getSignatureCertificate(
@@ -524,7 +525,7 @@ void FuConstructRectangle::Deactivate()
         }
     }
 
-    svx::SignatureLineHelper::setShapeCertificate(mpView, aCertificateOrName);
+    svx::SignatureLineHelper::setShapeCertificate(pViewShell, 
aCertificateOrName);
 
     // Update infobar to offer "finish signing".
     SfxViewFrame* pFrame = mpViewShell->GetViewFrame();
diff --git a/sd/source/ui/func/fusel.cxx b/sd/source/ui/func/fusel.cxx
index 8624c784fca5..bb6abf7dd8a3 100644
--- a/sd/source/ui/func/fusel.cxx
+++ b/sd/source/ui/func/fusel.cxx
@@ -205,7 +205,8 @@ bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
             bTextEdit = true;
 
         bool bPreventModify = mpDocSh->IsReadOnly();
-        if (bPreventModify && mpDocSh->GetSignPDFCertificate().Is())
+        SfxViewShell* pViewShell = mpViewShell->GetViewShell();
+        if (bPreventModify && pViewShell && 
pViewShell->GetSignPDFCertificate().Is())
         {
             // If the just added signature line shape is selected, allow 
moving / resizing it.
             bPreventModify = false;
diff --git a/sfx2/qa/cppunit/doc.cxx b/sfx2/qa/cppunit/doc.cxx
index 2f9d79068d07..5b541fd28461 100644
--- a/sfx2/qa/cppunit/doc.cxx
+++ b/sfx2/qa/cppunit/doc.cxx
@@ -22,6 +22,7 @@
 #include <comphelper/propertysequence.hxx>
 #include <comphelper/sequence.hxx>
 #include <svl/cryptosign.hxx>
+#include <sfx2/viewsh.hxx>
 
 using namespace com::sun::star;
 
@@ -53,14 +54,14 @@ CPPUNIT_TEST_FIXTURE(Test, testNoGrabBagShape)
     xController->select(aShape);
 
     // See if it has a signing certificate associated.
-    auto pBaseModel = dynamic_cast<SfxBaseModel*>(xModel.get());
-    CPPUNIT_ASSERT(pBaseModel);
-    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    SfxViewShell* pViewShell
+        = SfxViewShell::Get(uno::Reference<frame::XController>(xController, 
uno::UNO_QUERY));
+    CPPUNIT_ASSERT(pViewShell);
 
     // Without the accompanying fix in place, this test would have failed with:
     // An uncaught exception of type 
com.sun.star.beans.UnknownPropertyException
     // which was not caught later, resulting in a crash.
-    pObjectShell->GetSignPDFCertificate();
+    pViewShell->GetSignPDFCertificate();
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testTempFilePath)
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 3ba266116ba7..54c759c99eae 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -430,74 +430,6 @@ bool SfxObjectShell::IsSignPDF() const
     return false;
 }
 
-namespace
-{
-uno::Reference<beans::XPropertySet> GetSelectedShapeOfModel(const 
uno::Reference<frame::XModel>& xModel)
-{
-    if (!xModel.is())
-    {
-        return uno::Reference<beans::XPropertySet>();
-    }
-
-    uno::Reference<drawing::XShapes> xShapes(xModel->getCurrentSelection(), 
uno::UNO_QUERY);
-    if (!xShapes.is() || xShapes->getCount() < 1)
-    {
-        return uno::Reference<beans::XPropertySet>();
-    }
-
-    uno::Reference<beans::XPropertySet> xShapeProps(xShapes->getByIndex(0), 
uno::UNO_QUERY);
-    return xShapeProps;
-}
-}
-
-svl::crypto::CertificateOrName SfxObjectShell::GetSignPDFCertificate() const
-{
-    uno::Reference<beans::XPropertySet> xShapeProps = 
GetSelectedShapeOfModel(GetBaseModel());
-    if (!xShapeProps.is() || 
!xShapeProps->getPropertySetInfo()->hasPropertyByName(u"InteropGrabBag"_ustr))
-    {
-        return {};
-    }
-
-    comphelper::SequenceAsHashMap 
aMap(xShapeProps->getPropertyValue(u"InteropGrabBag"_ustr));
-    auto it = aMap.find(u"SignatureCertificate"_ustr);
-    if (it == aMap.end())
-    {
-        return {};
-    }
-
-    svl::crypto::CertificateOrName aCertificateOrName;
-    if (it->second.has<uno::Reference<security::XCertificate>>())
-    {
-        it->second >>= aCertificateOrName.m_xCertificate;
-    }
-    else
-    {
-        it->second >>= aCertificateOrName.m_aName;
-    }
-    return aCertificateOrName;
-}
-
-void SfxObjectShell::ResetSignPDFCertificate()
-{
-    uno::Reference<beans::XPropertySet> xShapeProps = 
GetSelectedShapeOfModel(GetBaseModel());
-    if 
(!xShapeProps->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
-    {
-        return;
-    }
-
-    comphelper::SequenceAsHashMap 
aMap(xShapeProps->getPropertyValue("InteropGrabBag"));
-    auto it = aMap.find("SignatureCertificate");
-    if (it == aMap.end())
-    {
-        return;
-    }
-
-    aMap.erase(it);
-    xShapeProps->setPropertyValue("InteropGrabBag", 
uno::Any(aMap.getAsConstPropertyValueList()));
-    // The shape's property is now reset, so the doc model is no longer 
modified.
-    SetModified(false);
-}
-
 static void sendErrorToLOK(const ErrCodeMsg& error)
 {
     if (error.GetCode().GetClass() == ErrCodeClass::NONE)
@@ -616,7 +548,9 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
 
         if (SID_SIGNATURE == nId)
         {
-            uno::Reference<security::XCertificate> xCertificate = 
GetSignPDFCertificate().m_xCertificate;
+            SfxViewFrame* pFrame = GetFrame();
+            SfxViewShell* pViewShell = pFrame ? pFrame->GetViewShell() : 
nullptr;
+            uno::Reference<security::XCertificate> xCertificate = pViewShell ? 
pViewShell->GetSignPDFCertificate().m_xCertificate : nullptr;
             if (xCertificate.is())
             {
 
@@ -627,9 +561,9 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
                 // Reset the picked certificate for PDF signing, then recheck 
signatures to show how
                 // the PDF actually looks like after signing.  Also change the 
"finish signing" on
                 // the infobar back to "sign document".
-                if (SfxViewFrame* pFrame = GetFrame())
+                if (pViewShell)
                 {
-                    ResetSignPDFCertificate();
+                    pViewShell->SetSignPDFCertificate({});
                     RecheckSignature(false);
                     pFrame->RemoveInfoBar(u"readonly");
                     pFrame->AppendReadOnlyInfobar();
@@ -676,8 +610,6 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
                     return;
                 }
 
-                SfxViewFrame* pFrame = GetFrame();
-                SfxViewShell* pViewShell = pFrame ? pFrame->GetViewShell() : 
nullptr;
                 if (pViewShell)
                 {
                     svl::crypto::CertificateOrName aCertificateOrName;
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index 2a32b003d2b9..791996653298 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -1275,8 +1275,8 @@ void SfxViewFrame::AppendReadOnlyInfobar()
     bool bSignWithCert = false;
     if (bSignPDF)
     {
-        SfxObjectShell* pObjectShell = GetObjectShell();
-        uno::Reference<security::XCertificate> xCertificate = 
pObjectShell->GetSignPDFCertificate().m_xCertificate;
+        SfxViewShell* pViewShell = GetViewShell();
+        uno::Reference<security::XCertificate> xCertificate = 
pViewShell->GetSignPDFCertificate().m_xCertificate;
         bSignWithCert = xCertificate.is();
     }
 
diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx
index e42a69ea27aa..10dcb366eefc 100644
--- a/sfx2/source/view/viewsh.cxx
+++ b/sfx2/source/view/viewsh.cxx
@@ -47,6 +47,7 @@
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/datatransfer/clipboard/XClipboardListener.hpp>
 #include <com/sun/star/datatransfer/clipboard/XClipboardNotifier.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
 #include <com/sun/star/view/XRenderable.hpp>
 #include <com/sun/star/uno/Reference.hxx>
 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
@@ -2817,6 +2818,83 @@ svl::crypto::CertificateOrName 
SfxViewShell::GetSigningCertificate() const
     return pImpl->m_aSigningCertificate;
 }
 
+namespace
+{
+uno::Reference<beans::XPropertySet>
+GetSelectedShapeOfView(const uno::Reference<frame::XController>& xController)
+{
+    uno::Reference<view::XSelectionSupplier> xSelectionSupplier(xController, 
uno::UNO_QUERY);
+    uno::Reference<drawing::XShapes> 
xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
+    if (!xShapes.is() || xShapes->getCount() != 1)
+    {
+        return {};
+    }
+
+    return uno::Reference<beans::XPropertySet>(xShapes->getByIndex(0), 
uno::UNO_QUERY);
+}
+}
+
+void SfxViewShell::SetSignPDFCertificate(const svl::crypto::CertificateOrName& 
rCertificateOrName)
+{
+    uno::Reference<beans::XPropertySet> xShape = 
GetSelectedShapeOfView(GetController());
+    if (!xShape.is() || 
!xShape->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
+    {
+        return;
+    }
+
+    comphelper::SequenceAsHashMap 
aMap(xShape->getPropertyValue("InteropGrabBag"));
+
+    auto it = aMap.find("SignatureCertificate");
+    if (rCertificateOrName.Is())
+    {
+        if (rCertificateOrName.m_xCertificate.is())
+        {
+            aMap["SignatureCertificate"] <<= rCertificateOrName.m_xCertificate;
+        }
+        else
+        {
+            aMap["SignatureCertificate"] <<= rCertificateOrName.m_aName;
+        }
+    }
+    else if (it != aMap.end())
+    {
+        aMap.erase(it);
+    }
+    xShape->setPropertyValue("InteropGrabBag", 
uno::Any(aMap.getAsConstPropertyValueList()));
+    if (!rCertificateOrName.Is())
+    {
+        // The shape's property is now reset, so the doc model is no longer 
modified.
+        GetObjectShell()->SetModified(false);
+    }
+}
+
+svl::crypto::CertificateOrName SfxViewShell::GetSignPDFCertificate() const
+{
+    uno::Reference<beans::XPropertySet> xShape = 
GetSelectedShapeOfView(GetController());
+    if (!xShape.is() || 
!xShape->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
+    {
+        return {};
+    }
+
+    comphelper::SequenceAsHashMap 
aMap(xShape->getPropertyValue("InteropGrabBag"));
+    auto it = aMap.find("SignatureCertificate");
+    if (it == aMap.end())
+    {
+        return {};
+    }
+
+    svl::crypto::CertificateOrName aCertificateOrName;
+    if (it->second.has<uno::Reference<security::XCertificate>>())
+    {
+        it->second >>= aCertificateOrName.m_xCertificate;
+    }
+    else
+    {
+        it->second >>= aCertificateOrName.m_aName;
+    }
+    return aCertificateOrName;
+}
+
 bool SfxViewShell::PrepareClose
 (
     bool bUI     // TRUE: Allow Dialog and so on, FALSE: silent-mode
diff --git a/svl/source/crypto/cryptosign.cxx b/svl/source/crypto/cryptosign.cxx
index 377214a05da2..f053d25134e5 100644
--- a/svl/source/crypto/cryptosign.cxx
+++ b/svl/source/crypto/cryptosign.cxx
@@ -2404,7 +2404,7 @@ void Signing::appendHex(sal_Int8 nInt, OStringBuffer& 
rBuffer)
     rBuffer.append( pHexDigits[ nInt & 15 ] );
 }
 
-bool CertificateOrName::Is()
+bool CertificateOrName::Is() const
 {
     return m_xCertificate.is() || !m_aName.isEmpty();
 }
diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx
index e2c6b58a9dac..b3262e588e94 100644
--- a/svx/qa/unit/svdraw.cxx
+++ b/svx/qa/unit/svdraw.cxx
@@ -862,10 +862,11 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testVisualSignResize)
     {
         return;
     }
-    SdrView* pView = SfxViewShell::Current()->GetDrawView();
+    SfxViewShell* pViewShell
+        = SfxViewShell::Get(uno::Reference<frame::XController>(xController, 
uno::UNO_QUERY));
     svl::crypto::CertificateOrName aCertificateOrName;
     aCertificateOrName.m_xCertificate = xCert;
-    svx::SignatureLineHelper::setShapeCertificate(pView, aCertificateOrName);
+    svx::SignatureLineHelper::setShapeCertificate(pViewShell, 
aCertificateOrName);
     pObjectShell->SetModified(false);
 
     // When resizing the shape by moving the bottom right (last) handle 
towards top right:
diff --git a/svx/source/dialog/signaturelinehelper.cxx 
b/svx/source/dialog/signaturelinehelper.cxx
index d8a41e8d3cc7..d4f286995f2b 100644
--- a/svx/source/dialog/signaturelinehelper.cxx
+++ b/svx/source/dialog/signaturelinehelper.cxx
@@ -34,6 +34,7 @@
 #include <unotools/syslocale.hxx>
 #include <vcl/weld.hxx>
 #include <sfx2/digitalsignatures.hxx>
+#include <sfx2/viewsh.hxx>
 
 using namespace com::sun::star;
 
@@ -135,9 +136,10 @@ uno::Reference<graphic::XGraphic> 
importSVG(std::u16string_view rSVG)
     return xGraphic;
 }
 
-void setShapeCertificate(const SdrView* pView,
+void setShapeCertificate(SfxViewShell* pViewShell,
                          const svl::crypto::CertificateOrName& 
rCertificateOrName)
 {
+    const SdrView* pView = pViewShell->GetDrawView();
     const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
     if (rMarkList.GetMarkCount() < 1)
     {
@@ -154,16 +156,7 @@ void setShapeCertificate(const SdrView* pView,
     // Remember the selected certificate.
     uno::Reference<drawing::XShape> xShape = pSignatureLine->getUnoShape();
     uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
-    comphelper::SequenceAsHashMap 
aMap(xShapeProps->getPropertyValue(u"InteropGrabBag"_ustr));
-    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()));
+    pViewShell->SetSignPDFCertificate(rCertificateOrName);
 
     // Read svg and replace placeholder texts.
     OUString aSvgImage(
diff --git a/svx/source/svdraw/svddrgv.cxx b/svx/source/svdraw/svddrgv.cxx
index 02cfc5ee38c8..645cb8fd2bef 100644
--- a/svx/source/svdraw/svddrgv.cxx
+++ b/svx/source/svdraw/svddrgv.cxx
@@ -415,8 +415,7 @@ bool SdrDragView::BegDragObj(const Point& rPnt, 
OutputDevice* pOut, SdrHdl* pHdl
                             {
                                 bool bResizeAllowed = IsResizeAllowed(true);
                                 SfxViewShell* pViewShell = GetSfxViewShell();
-                                SfxObjectShell* pObjectShell = pViewShell ? 
pViewShell->GetObjectShell() : nullptr;
-                                if (!bResizeAllowed && pObjectShell && 
pObjectShell->GetSignPDFCertificate().Is())
+                                if (!bResizeAllowed && pViewShell && 
pViewShell->GetSignPDFCertificate().Is())
                                 {
                                     // If the just added signature line shape 
is selected, allow resizing it.
                                     bResizeAllowed = true;
diff --git a/svx/source/svdraw/svdedtv1.cxx b/svx/source/svdraw/svdedtv1.cxx
index 2e7cbe6c5c7d..d35ace8a11bc 100644
--- a/svx/source/svdraw/svdedtv1.cxx
+++ b/svx/source/svdraw/svdedtv1.cxx
@@ -1829,8 +1829,7 @@ void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& 
rAttr, bool addPageMargin
     // change position
     bool bMoveAllowed = m_bMoveAllowed;
     SfxViewShell* pViewShell = GetSfxViewShell();
-    SfxObjectShell* pObjectShell = pViewShell ? pViewShell->GetObjectShell() : 
nullptr;
-    if (!bMoveAllowed && pObjectShell && 
pObjectShell->GetSignPDFCertificate().Is())
+    if (!bMoveAllowed && pViewShell && 
pViewShell->GetSignPDFCertificate().Is())
     {
         // If the just added signature line shape is selected, allow moving it.
         bMoveAllowed = true;
diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index c4f096dd04a8..0e24fe898e3f 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -1116,7 +1116,7 @@ void SdrMarkView::SetMarkHandlesForLOKit(tools::Rectangle 
const & rRect, const S
             else
             {
                 SfxObjectShell* pObjectShell = pViewShell ? 
pViewShell->GetObjectShell() : nullptr;
-                if (pObjectShell && pObjectShell->IsSignPDF() && 
pObjectShell->GetSignPDFCertificate().Is())
+                if (pObjectShell && pObjectShell->IsSignPDF() && pViewShell && 
pViewShell->GetSignPDFCertificate().Is())
                 {
                     // Expose the info that this is the special signature 
widget that is OK to
                     // move/resize.
diff --git a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx 
b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx
index 9964ec88dfb2..243687dad00b 100644
--- a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx
+++ b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx
@@ -102,10 +102,9 @@ CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, 
testPDFAddVisibleSignatureLastPage)
     }
     SfxViewShell* pCurrent = SfxViewShell::Current();
     CPPUNIT_ASSERT(pCurrent);
-    SdrView* pView = pCurrent->GetDrawView();
     svl::crypto::CertificateOrName aCertificateOrName;
     aCertificateOrName.m_xCertificate = xCert;
-    svx::SignatureLineHelper::setShapeCertificate(pView, aCertificateOrName);
+    svx::SignatureLineHelper::setShapeCertificate(pCurrent, 
aCertificateOrName);
 
     // the document is modified now, but Sign function can't show SaveAs dialog
     // in unit test, so just clear the modified
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index 82a7d2a1ae73..bb2c4d5df992 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -773,10 +773,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, 
testPDFAddVisibleSignature)
     }
     SfxViewShell* pCurrent = SfxViewShell::Current();
     CPPUNIT_ASSERT(pCurrent);
-    SdrView* pView = pCurrent->GetDrawView();
     svl::crypto::CertificateOrName aCertificateOrName;
     aCertificateOrName.m_xCertificate = xCert;
-    svx::SignatureLineHelper::setShapeCertificate(pView, aCertificateOrName);
+    svx::SignatureLineHelper::setShapeCertificate(pCurrent, 
aCertificateOrName);
 
     // the document is modified now, but Sign function can't show SaveAs dialog
     // in unit test, so just clear the modified
diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx 
b/xmlsecurity/source/helper/pdfsignaturehelper.cxx
index 79ee45c0e3c3..8d316bcffd91 100644
--- a/xmlsecurity/source/helper/pdfsignaturehelper.cxx
+++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx
@@ -33,6 +33,7 @@
 #include <vcl/checksum.hxx>
 #include <svl/cryptosign.hxx>
 #include <vcl/filter/PDFiumLibrary.hxx>
+#include <sfx2/viewsh.hxx>
 
 using namespace ::com::sun::star;
 
@@ -70,21 +71,14 @@ void GetSignatureLineShape(const 
uno::Reference<frame::XModel>& xModel, sal_Int3
         return;
     }
 
-    uno::Reference<drawing::XShapes> xShapes(xModel->getCurrentSelection(), 
uno::UNO_QUERY);
-    if (!xShapes.is() || xShapes->getCount() < 1)
-    {
-        return;
-    }
-
-    uno::Reference<beans::XPropertySet> xShapeProps(xShapes->getByIndex(0), 
uno::UNO_QUERY);
-    if (!xShapeProps.is())
+    SfxViewShell* pViewShell = 
SfxViewShell::Get(xModel->getCurrentController());
+    if (!pViewShell || !pViewShell->GetSignPDFCertificate().Is())
     {
         return;
     }
 
-    comphelper::SequenceAsHashMap 
aMap(xShapeProps->getPropertyValue(u"InteropGrabBag"_ustr));
-    auto it = aMap.find(u"SignatureCertificate"_ustr);
-    if (it == aMap.end())
+    uno::Reference<drawing::XShapes> xShapes(xModel->getCurrentSelection(), 
uno::UNO_QUERY);
+    if (!xShapes.is() || xShapes->getCount() < 1)
     {
         return;
     }
commit 7f791b643244a34d6fcaf44b420ebfc0af91ada7
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Jan 15 09:32:30 2025 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Feb 12 10:43:33 2025 +0100

    cool#10630 doc electronic sign: fix no graphic selection for the signature 
line
    
    Insert a signature line in "extern" mode, the shape gets selected but
    there is no graphic selection at a LOK API level.
    
    This is because GetSignPDFCertificate() returned an XCertificate, which
    is empty in the external signing case, so we can't differentiate between
    no signing and external signing.
    
    Fix this by changing the return type to svl::crypto::CertificateOrName,
    this way SdrMarkView::SetMarkHandlesForLOKit() can annotate the
    signature line correctly even in the external signing case.
    
    The tracking of the signature line selection is still in the model (not
    in the view), that's not yet fixed here.
    
    Change-Id: I4ef9c1fa0a88af0c0fcd55156b973a3705f985c0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180296
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index f6fd9ca3fb9d..9fc11e799571 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -5175,7 +5175,7 @@ static bool isCommandAllowed(OUString& command) {
                 {
                     // If the just added signature line shape is selected, 
allow moving it.
                     SfxObjectShell* pDocShell = pViewShell->GetObjectShell();
-                    bRet = pDocShell->GetSignPDFCertificate().is();
+                    bRet = pDocShell->GetSignPDFCertificate().Is();
                 }
                 return bRet;
             }
diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index 83e0fac51af8..d97ce8e13a38 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -111,6 +111,7 @@ namespace com::sun::star::security { struct 
DocumentSignatureInformation; }
 namespace com::sun::star::task { class XInteractionHandler; }
 namespace com::sun::star::lang { class XComponent; }
 namespace com::sun::star::text { class XTextRange; }
+namespace svl::crypto { class CertificateOrName; }
 
 #define SFX_TITLE_TITLE    0
 #define SFX_TITLE_FILENAME 1
@@ -813,7 +814,7 @@ public:
     bool IsSignPDF() const;
 
     /// Gets the certificate that is already picked by the user but not yet 
used for signing.
-    css::uno::Reference<css::security::XCertificate> GetSignPDFCertificate() 
const;
+    svl::crypto::CertificateOrName GetSignPDFCertificate() const;
 
     void ResetSignPDFCertificate();
 
diff --git a/include/svl/cryptosign.hxx b/include/svl/cryptosign.hxx
index 291201cd394a..25a4428ce1ad 100644
--- a/include/svl/cryptosign.hxx
+++ b/include/svl/cryptosign.hxx
@@ -127,6 +127,9 @@ public:
     /// Otherwise we don't have a certificate but have a name to be featured 
on the visual
     /// signature.
     OUString m_aName;
+
+    /// Returns if a certificate or a name is set.
+    bool Is();
 };
 
 }
diff --git a/sd/qa/unit/tiledrendering/tiledrendering2.cxx 
b/sd/qa/unit/tiledrendering/tiledrendering2.cxx
index bf9f7db738a4..5b56c5033966 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering2.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering2.cxx
@@ -47,9 +47,11 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testInsertSignatureLineExternal)
     uno::Sequence<beans::PropertyValue> aArgs = { 
comphelper::makePropertyValue("ReadOnly", true) };
     loadWithParams(createFileURL(u"empty.pdf"), aArgs);
     SdXImpressDocument* pImpressDocument = 
dynamic_cast<SdXImpressDocument*>(mxComponent.get());
+    pImpressDocument->initializeForTiledRendering({});
     sd::ViewShell* pViewShell = 
pImpressDocument->GetDocShell()->GetViewShell();
     sd::View* pView = pViewShell->GetView();
     pView->SetAuthor("myauthor");
+    ViewCallback aView;
 
     // When insrerting a signature line for electronic (extrenal) signing:
     aArgs = {
@@ -66,6 +68,28 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testInsertSignatureLineExternal)
     aMarkedObjects[0]->GetGrabBagItem(aAny);
     comphelper::SequenceAsHashMap aMap(aAny);
     CPPUNIT_ASSERT(aMap.contains("SignatureCertificate"));
+    // Also verify that this is exposed at a LOK level:
+    OString aShapeSelection = "[" + aView.m_ShapeSelection + "]";
+    const char* pShapeSelectionStr = aShapeSelection.getStr();
+    std::stringstream aStream(pShapeSelectionStr);
+    boost::property_tree::ptree aTree;
+    boost::property_tree::read_json(aStream, aTree);
+    int nCount = 0;
+    bool bSignature = false;
+    for (const auto& i : aTree)
+    {
+        ++nCount;
+        if (nCount <= 5)
+        {
+            // x, y, w, h, part
+            continue;
+        }
+        boost::property_tree::ptree aProps = i.second;
+        // Without the accompanying fix in place, this test would have failed 
with:
+        // - No such node (isSignature)
+        bSignature = aProps.get<bool>("isSignature");
+    }
+    CPPUNIT_ASSERT(bSignature);
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/ui/func/fusel.cxx b/sd/source/ui/func/fusel.cxx
index aa43a76ee91b..8624c784fca5 100644
--- a/sd/source/ui/func/fusel.cxx
+++ b/sd/source/ui/func/fusel.cxx
@@ -61,6 +61,7 @@
 
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <comphelper/lok.hxx>
+#include <svl/cryptosign.hxx>
 
 using namespace ::com::sun::star;
 
@@ -204,7 +205,7 @@ bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
             bTextEdit = true;
 
         bool bPreventModify = mpDocSh->IsReadOnly();
-        if (bPreventModify && mpDocSh->GetSignPDFCertificate().is())
+        if (bPreventModify && mpDocSh->GetSignPDFCertificate().Is())
         {
             // If the just added signature line shape is selected, allow 
moving / resizing it.
             bPreventModify = false;
diff --git a/sfx2/qa/cppunit/doc.cxx b/sfx2/qa/cppunit/doc.cxx
index b16c078ef412..2f9d79068d07 100644
--- a/sfx2/qa/cppunit/doc.cxx
+++ b/sfx2/qa/cppunit/doc.cxx
@@ -21,6 +21,7 @@
 #include <comphelper/sequenceashashmap.hxx>
 #include <comphelper/propertysequence.hxx>
 #include <comphelper/sequence.hxx>
+#include <svl/cryptosign.hxx>
 
 using namespace com::sun::star;
 
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 6741e09623c2..3ba266116ba7 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -450,22 +450,31 @@ uno::Reference<beans::XPropertySet> 
GetSelectedShapeOfModel(const uno::Reference
 }
 }
 
-uno::Reference<security::XCertificate> SfxObjectShell::GetSignPDFCertificate() 
const
+svl::crypto::CertificateOrName SfxObjectShell::GetSignPDFCertificate() const
 {
     uno::Reference<beans::XPropertySet> xShapeProps = 
GetSelectedShapeOfModel(GetBaseModel());
     if (!xShapeProps.is() || 
!xShapeProps->getPropertySetInfo()->hasPropertyByName(u"InteropGrabBag"_ustr))
     {
-        return uno::Reference<security::XCertificate>();
+        return {};
     }
 
     comphelper::SequenceAsHashMap 
aMap(xShapeProps->getPropertyValue(u"InteropGrabBag"_ustr));
     auto it = aMap.find(u"SignatureCertificate"_ustr);
     if (it == aMap.end())
     {
-        return uno::Reference<security::XCertificate>();
+        return {};
     }
 
-    return uno::Reference<security::XCertificate>(it->second, uno::UNO_QUERY);
+    svl::crypto::CertificateOrName aCertificateOrName;
+    if (it->second.has<uno::Reference<security::XCertificate>>())
+    {
+        it->second >>= aCertificateOrName.m_xCertificate;
+    }
+    else
+    {
+        it->second >>= aCertificateOrName.m_aName;
+    }
+    return aCertificateOrName;
 }
 
 void SfxObjectShell::ResetSignPDFCertificate()
@@ -607,7 +616,7 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
 
         if (SID_SIGNATURE == nId)
         {
-            uno::Reference<security::XCertificate> xCertificate = 
GetSignPDFCertificate();
+            uno::Reference<security::XCertificate> xCertificate = 
GetSignPDFCertificate().m_xCertificate;
             if (xCertificate.is())
             {
 
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index e70cceeffe70..2a32b003d2b9 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -132,6 +132,7 @@
 #include "impviewframe.hxx"
 #include <vcl/commandinfoprovider.hxx>
 #include <vcl/svapp.hxx>
+#include <svl/cryptosign.hxx>
 
 #define ShellClass_SfxViewFrame
 #include <sfxslots.hxx>
@@ -1275,7 +1276,7 @@ void SfxViewFrame::AppendReadOnlyInfobar()
     if (bSignPDF)
     {
         SfxObjectShell* pObjectShell = GetObjectShell();
-        uno::Reference<security::XCertificate> xCertificate = 
pObjectShell->GetSignPDFCertificate();
+        uno::Reference<security::XCertificate> xCertificate = 
pObjectShell->GetSignPDFCertificate().m_xCertificate;
         bSignWithCert = xCertificate.is();
     }
 
diff --git a/svl/source/crypto/cryptosign.cxx b/svl/source/crypto/cryptosign.cxx
index 6a5f08077765..377214a05da2 100644
--- a/svl/source/crypto/cryptosign.cxx
+++ b/svl/source/crypto/cryptosign.cxx
@@ -2403,6 +2403,11 @@ void Signing::appendHex(sal_Int8 nInt, OStringBuffer& 
rBuffer)
     rBuffer.append( pHexDigits[ (nInt >> 4) & 15 ] );
     rBuffer.append( pHexDigits[ nInt & 15 ] );
 }
+
+bool CertificateOrName::Is()
+{
+    return m_xCertificate.is() || !m_aName.isEmpty();
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/svdraw/svddrgv.cxx b/svx/source/svdraw/svddrgv.cxx
index 9b05f0206539..02cfc5ee38c8 100644
--- a/svx/source/svdraw/svddrgv.cxx
+++ b/svx/source/svdraw/svddrgv.cxx
@@ -40,6 +40,7 @@
 #include <officecfg/Office/Common.hxx>
 #include <sfx2/objsh.hxx>
 #include <sfx2/viewsh.hxx>
+#include <svl/cryptosign.hxx>
 
 using namespace sdr;
 
@@ -415,7 +416,7 @@ bool SdrDragView::BegDragObj(const Point& rPnt, 
OutputDevice* pOut, SdrHdl* pHdl
                                 bool bResizeAllowed = IsResizeAllowed(true);
                                 SfxViewShell* pViewShell = GetSfxViewShell();
                                 SfxObjectShell* pObjectShell = pViewShell ? 
pViewShell->GetObjectShell() : nullptr;
-                                if (!bResizeAllowed && pObjectShell && 
pObjectShell->GetSignPDFCertificate().is())
+                                if (!bResizeAllowed && pObjectShell && 
pObjectShell->GetSignPDFCertificate().Is())
                                 {
                                     // If the just added signature line shape 
is selected, allow resizing it.
                                     bResizeAllowed = true;
diff --git a/svx/source/svdraw/svdedtv1.cxx b/svx/source/svdraw/svdedtv1.cxx
index 00034815fb7b..2e7cbe6c5c7d 100644
--- a/svx/source/svdraw/svdedtv1.cxx
+++ b/svx/source/svdraw/svdedtv1.cxx
@@ -70,6 +70,7 @@
 #include <comphelper/lok.hxx>
 #include <osl/diagnose.h>
 #include <sfx2/objsh.hxx>
+#include <svl/cryptosign.hxx>
 
 // EditView
 
@@ -1829,7 +1830,7 @@ void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& 
rAttr, bool addPageMargin
     bool bMoveAllowed = m_bMoveAllowed;
     SfxViewShell* pViewShell = GetSfxViewShell();
     SfxObjectShell* pObjectShell = pViewShell ? pViewShell->GetObjectShell() : 
nullptr;
-    if (!bMoveAllowed && pObjectShell && 
pObjectShell->GetSignPDFCertificate().is())
+    if (!bMoveAllowed && pObjectShell && 
pObjectShell->GetSignPDFCertificate().Is())
     {
         // If the just added signature line shape is selected, allow moving it.
         bMoveAllowed = true;
diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index 8ba5583853a1..c4f096dd04a8 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -65,6 +65,7 @@
 #include <svtools/optionsdrawinglayer.hxx>
 
 #include <drawinglayer/processor2d/textextractor2d.hxx>
+#include <svl/cryptosign.hxx>
 
 #include <array>
 
@@ -1115,7 +1116,7 @@ void SdrMarkView::SetMarkHandlesForLOKit(tools::Rectangle 
const & rRect, const S
             else
             {
                 SfxObjectShell* pObjectShell = pViewShell ? 
pViewShell->GetObjectShell() : nullptr;
-                if (pObjectShell && pObjectShell->IsSignPDF() && 
pObjectShell->GetSignPDFCertificate().is())
+                if (pObjectShell && pObjectShell->IsSignPDF() && 
pObjectShell->GetSignPDFCertificate().Is())
                 {
                     // Expose the info that this is the special signature 
widget that is OK to
                     // move/resize.
commit 00d0ab590fb38bcb1425bd7e601b202b41ffdae1
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Jan 13 11:18:12 2025 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Feb 12 10:43:33 2025 +0100

    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 <vmik...@collabora.com>

diff --git a/cui/source/dialogs/SignSignatureLineDialog.cxx 
b/cui/source/dialogs/SignSignatureLineDialog.cxx
index a1cf837c107c..cb6a7191c436 100644
--- a/cui/source/dialogs/SignSignatureLineDialog.cxx
+++ b/cui/source/dialogs/SignSignatureLineDialog.cxx
@@ -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]", "");
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 14f260a0e52e..f6fd9ca3fb9d 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -4513,7 +4513,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);
             }
         }
 
diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx
index bfd43c67101e..9d64937d6dc5 100644
--- a/include/sfx2/viewsh.hxx
+++ b/include/sfx2/viewsh.hxx
@@ -76,6 +76,7 @@ namespace com::sun::star::view { class XRenderable; }
 namespace com::sun::star::security { class XCertificate; }
 namespace tools { class Rectangle; }
 namespace svtools { enum ColorConfigEntry : int; }
+namespace svl::crypto { class CertificateOrName; }
 
 enum class SfxPrinterChangeFlags
 {
@@ -496,8 +497,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
diff --git a/include/svl/cryptosign.hxx b/include/svl/cryptosign.hxx
index 8c8e48f0da54..291201cd394a 100644
--- a/include/svl/cryptosign.hxx
+++ b/include/svl/cryptosign.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: */
diff --git a/include/svx/signaturelinehelper.hxx 
b/include/svx/signaturelinehelper.hxx
index e8105a37bd7f..6f17f3726dd2 100644
--- a/include/svx/signaturelinehelper.hxx
+++ b/include/svx/signaturelinehelper.hxx
@@ -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
diff --git a/sd/qa/unit/tiledrendering/data/empty.pdf 
b/sd/qa/unit/tiledrendering/data/empty.pdf
new file mode 100644
index 000000000000..d6142103184b
Binary files /dev/null and b/sd/qa/unit/tiledrendering/data/empty.pdf differ
diff --git a/sd/qa/unit/tiledrendering/tiledrendering2.cxx 
b/sd/qa/unit/tiledrendering/tiledrendering2.cxx
index 28860a293b41..bf9f7db738a4 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering2.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering2.cxx
@@ -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: */
diff --git a/sd/source/ui/func/fuconrec.cxx b/sd/source/ui/func/fuconrec.cxx
index 5cbdb1e82596..2e4e7a9cfcb2 100644
--- a/sd/source/ui/func/fuconrec.cxx
+++ b/sd/source/ui/func/fuconrec.cxx
@@ -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();
diff --git a/sd/source/ui/view/drviewse.cxx b/sd/source/ui/view/drviewse.cxx
index ea2f65a01c00..f9466b51a3d1 100644
--- a/sd/source/ui/view/drviewse.cxx
+++ b/sd/source/ui/view/drviewse.cxx
@@ -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);
                 }
             }
 
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index c18da34283ef..6741e09623c2 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -671,13 +671,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.
diff --git a/sfx2/source/view/viewimp.hxx b/sfx2/source/view/viewimp.hxx
index 1dc24eec7a82..83279ae84cee 100644
--- a/sfx2/source/view/viewimp.hxx
+++ b/sfx2/source/view/viewimp.hxx
@@ -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();
diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx
index d743cd5ddd02..e42a69ea27aa 100644
--- a/sfx2/source/view/viewsh.cxx
+++ b/sfx2/source/view/viewsh.cxx
@@ -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
diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx
index 6cf4c6bc10f3..e2c6b58a9dac 100644
--- a/svx/qa/unit/svdraw.cxx
+++ b/svx/qa/unit/svdraw.cxx
@@ -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:
diff --git a/svx/sdi/svx.sdi b/svx/sdi/svx.sdi
index 449cd55d36d9..edc54923f4d0 100644
--- a/svx/sdi/svx.sdi
+++ b/svx/sdi/svx.sdi
@@ -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,
diff --git a/svx/source/dialog/signaturelinehelper.cxx 
b/svx/source/dialog/signaturelinehelper.cxx
index e079d62d5631..d8a41e8d3cc7 100644
--- a/svx/source/dialog/signaturelinehelper.cxx
+++ b/svx/source/dialog/signaturelinehelper.cxx
@@ -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);
diff --git a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx 
b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx
index b910f55820f0..9964ec88dfb2 100644
--- a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx
+++ b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx
@@ -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
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index 00a835119642..82a7d2a1ae73 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -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
diff --git a/xmlsecurity/source/dialogs/certificatechooser.cxx 
b/xmlsecurity/source/dialogs/certificatechooser.cxx
index 89fef57d032d..48dd33533efe 100644
--- a/xmlsecurity/source/dialogs/certificatechooser.cxx
+++ b/xmlsecurity/source/dialogs/certificatechooser.cxx
@@ -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
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx 
b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index aa4bfec4664b..6fef34748469 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -264,7 +264,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();
         }
commit 1b73db385d90f6a1f5251ebbad989d59b10c36e5
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Jan 9 11:52:47 2025 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Feb 12 10:43:33 2025 +0100

    cool#10630 lok doc sign: allow setting the size of the Impress sign line
    
    Insert a signature line in LOK mode when PEM certs are configured,
    moving the just inserted shape works (even in the read-only PDF view),
    but you can't resize the shape.
    
    This is because moving goes via .uno:TransformDialog, while resizing
    uses .uno:MoveShapeHandle.
    
    Fix this similar to moving, by allowing the operation when the shape is
    a just inserted signature line. Allowing the command in read-only mode
    is meant to be safe, since the command implementation again checks if
    the resize is allowed, and there we allow this only for signature lines.
    
    Also expose the "is signature line" info on the LOK API, so it can show
    the graphic selection handles conditionally (only when resize will be
    allowed).
    
    Change-Id: Ie85aa1211564758dc24ff83b4241de78a8e69ffc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180065
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sd/sdi/_drvwsh.sdi b/sd/sdi/_drvwsh.sdi
index 917d369ac8fc..b0c655176b1b 100644
--- a/sd/sdi/_drvwsh.sdi
+++ b/sd/sdi/_drvwsh.sdi
@@ -2966,6 +2966,7 @@ interface DrawView
     SID_MOVE_SHAPE_HANDLE
     [
         ExecMethod = FuTemporary ;
+        ReadOnlyDoc = TRUE ;
     ]
     SID_ATTR_TEXTCOLUMNS_NUMBER
     [
diff --git a/svx/qa/unit/data/empty.pdf b/svx/qa/unit/data/empty.pdf
new file mode 100644
index 000000000000..d6142103184b
Binary files /dev/null and b/svx/qa/unit/data/empty.pdf differ
diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx
index 12cdd6093f20..6cf4c6bc10f3 100644
--- a/svx/qa/unit/svdraw.cxx
+++ b/svx/qa/unit/svdraw.cxx
@@ -17,6 +17,9 @@
 #include <com/sun/star/drawing/LineStyle.hpp>
 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
+#include <com/sun/star/drawing/XDrawView.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
 
 #include <extendedprimitive2dxmldump.hxx>
 #include <rtl/ustring.hxx>
@@ -35,6 +38,10 @@
 #include <svl/itempool.hxx>
 #include <svx/svdomedia.hxx>
 #include <vcl/filter/PDFiumLibrary.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <sfx2/sfxbasemodel.hxx>
+#include <svx/signaturelinehelper.hxx>
+#include <sfx2/objsh.hxx>
 
 #include <sdr/contact/objectcontactofobjlistpainter.hxx>
 
@@ -45,16 +52,35 @@ namespace
 /// Tests for svx/source/svdraw/ code.
 class SvdrawTest : public UnoApiXmlTest
 {
+private:
+    uno::Reference<xml::crypto::XSEInitializer> mxSEInitializer;
+    uno::Reference<xml::crypto::XXMLSecurityContext> mxSecurityContext;
+
 public:
     SvdrawTest()
         : UnoApiXmlTest(u"svx/qa/unit/data/"_ustr)
     {
     }
 
+    void setUp() override;
+    uno::Reference<xml::crypto::XXMLSecurityContext>& getSecurityContext()
+    {
+        return mxSecurityContext;
+    }
+
 protected:
     SdrPage* getFirstDrawPageWithAssert();
 };
 
+void SvdrawTest::setUp()
+{
+    UnoApiTest::setUp();
+    MacrosTest::setUpX509(m_directories, "svx_unit");
+
+    mxSEInitializer = xml::crypto::SEInitializer::create(m_xContext);
+    mxSecurityContext = mxSEInitializer->createSecurityContext(OUString());
+}
+
 SdrPage* SvdrawTest::getFirstDrawPageWithAssert()
 {
     uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent,
@@ -800,6 +826,62 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testTdf161724)
     CPPUNIT_ASSERT_EQUAL(sal_Int16(9901), nBmpWidth);
     CPPUNIT_ASSERT_EQUAL(sal_Int16(12693), nBmpHeight);
 }
+
+CPPUNIT_TEST_FIXTURE(SvdrawTest, testVisualSignResize)
+{
+    // Given a read-only document with a just inserted signature line:
+    uno::Sequence<beans::PropertyValue> aArgs = { 
comphelper::makePropertyValue("ReadOnly", true) };
+    loadWithParams(createFileURL(u"empty.pdf"), aArgs);
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT(pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT(pObjectShell);
+    CPPUNIT_ASSERT(pObjectShell->IsReadOnly());
+    // Add a signature line to the 2nd page.
+    uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<drawing::XShape> xShape(
+        xFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), 
uno::UNO_QUERY);
+    xShape->setPosition(awt::Point(1000, 1000));
+    xShape->setSize(awt::Size(10000, 10000));
+    uno::Reference<drawing::XDrawPagesSupplier> xSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPages> xDrawPages = xSupplier->getDrawPages();
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xDrawPages->getCount());
+
+    uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawView> 
xController(xModel->getCurrentController(), uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), 
uno::UNO_QUERY);
+    xController->setCurrentPage(xDrawPage);
+    xDrawPage->add(xShape);
+    // Select it and assign a certificate.
+    uno::Reference<view::XSelectionSupplier> 
xSelectionSupplier(pBaseModel->getCurrentController(),
+                                                                
uno::UNO_QUERY);
+    xSelectionSupplier->select(uno::Any(xShape));
+    auto xEnv = getSecurityContext()->getSecurityEnvironment();
+    auto xCert = GetValidCertificate(xEnv->getPersonalCertificates(), xEnv);
+    if (!xCert)
+    {
+        return;
+    }
+    SdrView* pView = SfxViewShell::Current()->GetDrawView();
+    svx::SignatureLineHelper::setShapeCertificate(pView, xCert);
+    pObjectShell->SetModified(false);
+
+    // When resizing the shape by moving the bottom right (last) handle 
towards top right:
+    aArgs = {
+        comphelper::makePropertyValue("HandleNum", static_cast<sal_Int32>(7)),
+        comphelper::makePropertyValue("NewPosX", static_cast<sal_Int32>(1500)),
+        comphelper::makePropertyValue("NewPosY", static_cast<sal_Int32>(1500)),
+    };
+    dispatchCommand(mxComponent, ".uno:MoveShapeHandle", aArgs);
+
+    // Then make sure the size decreases:
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected less than: 10000
+    // - Actual  : 10000
+    // i.e. you could not resize even a just inserted signature line in a 
read-only view.
+    CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(10000), 
xShape->getSize().Width);
+    CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(10000), 
xShape->getSize().Height);
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/svdraw/svddrgv.cxx b/svx/source/svdraw/svddrgv.cxx
index 051e559c94cd..9b05f0206539 100644
--- a/svx/source/svdraw/svddrgv.cxx
+++ b/svx/source/svdraw/svddrgv.cxx
@@ -38,6 +38,8 @@
 #include <unotools/configmgr.hxx>
 #include <comphelper/lok.hxx>
 #include <officecfg/Office/Common.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewsh.hxx>
 
 using namespace sdr;
 
@@ -410,7 +412,15 @@ bool SdrDragView::BegDragObj(const Point& rPnt, 
OutputDevice* pOut, SdrHdl* pHdl
                             }
                             else
                             {
-                                if(!IsResizeAllowed(true))
+                                bool bResizeAllowed = IsResizeAllowed(true);
+                                SfxViewShell* pViewShell = GetSfxViewShell();
+                                SfxObjectShell* pObjectShell = pViewShell ? 
pViewShell->GetObjectShell() : nullptr;
+                                if (!bResizeAllowed && pObjectShell && 
pObjectShell->GetSignPDFCertificate().is())
+                                {
+                                    // If the just added signature line shape 
is selected, allow resizing it.
+                                    bResizeAllowed = true;
+                                }
+                                if(!bResizeAllowed)
                                 {
                                     return false;
                                 }
diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index 96bd7be18b7b..8ba5583853a1 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -61,6 +61,7 @@
 #include <sfx2/lokhelper.hxx>
 #include <sfx2/lokcomponenthelpers.hxx>
 #include <sfx2/viewsh.hxx>
+#include <sfx2/objsh.hxx>
 #include <svtools/optionsdrawinglayer.hxx>
 
 #include <drawinglayer/processor2d/textextractor2d.hxx>
@@ -1111,6 +1112,16 @@ void 
SdrMarkView::SetMarkHandlesForLOKit(tools::Rectangle const & rRect, const S
                     }
                 }
             }
+            else
+            {
+                SfxObjectShell* pObjectShell = pViewShell ? 
pViewShell->GetObjectShell() : nullptr;
+                if (pObjectShell && pObjectShell->IsSignPDF() && 
pObjectShell->GetSignPDFCertificate().is())
+                {
+                    // Expose the info that this is the special signature 
widget that is OK to
+                    // move/resize.
+                    aExtraInfo.append(", \"isSignature\": true");
+                }
+            }
             if (!bTableSelection && !pOtherShell && maHdlList.GetHdlCount())
             {
                 boost::property_tree::ptree responseJSON;

Reply via email to