include/sfx2/objsh.hxx      |    2 +
 sfx2/source/doc/objserv.cxx |   72 ++++++++++++++++++++++++++++----------------
 2 files changed, 48 insertions(+), 26 deletions(-)

New commits:
commit 641733ad2cac2dc496c4dcefa39d03efa6044dfb
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Jan 6 10:17:42 2025 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Mon Jan 6 15:30:15 2025 +0100

    cool#10630 doc sign: fix Impress sign line, to be able to finish signing 
again
    
    Open a PDF for signing on the desktop, insert a signature line, click
    the "finish signing" button on the infobar, Draw first asks if you want
    to save your modified document as ODG, then crashes.
    
    The first problem is that opening a PDF for signing and adding a
    signature line / visual signature didn't result in a modified doc model,
    but that now happens since commit
    aca32a55456aa4e907b216fb490b3c15d26c3d55 (tdf#146547 sfx2: allow
    read-only documents to be modified, 2023-06-16). Probably we want to
    keep this feaature that read-only documents can be modified in some
    cases, so explicitly mark the PDF document as not-modified before
    signing in SfxObjectShell::SignDocumentContentUsingCertificate().
    
    The other problem is that visual signing tried to reload the document:
    this is handy, as it shows if our PDF export worked correctly, but
    reloading is problematic since the signing code moved to async and it
    assumes that the underlying object shell is never deleted, so callbacks
    can have a pointer to it without worrying about the lifecycle. Fix this
    problem by not reloading, but clearing the marker on the signature shape
    and invalidating the signature status, instead of reloading, in
    SfxObjectShell::ExecFile_Impl().
    
    With this, visual signing of an existing PDF file works again in desktop
    Draw.
    
    Change-Id: I743983947d4607aa06674a1329bc8efb5af8a6d9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179821
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index a9db2f444e9f..bc173c48ad55 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -808,6 +808,8 @@ public:
     /// Gets the certificate that is already picked by the user but not yet 
used for signing.
     css::uno::Reference<css::security::XCertificate> 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/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 65103489bc97..3be01c98919d 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -431,39 +431,63 @@ bool SfxObjectShell::IsSignPDF() const
     return false;
 }
 
-uno::Reference<security::XCertificate> SfxObjectShell::GetSignPDFCertificate() 
const
+namespace
+{
+uno::Reference<beans::XPropertySet> GetSelectedShapeOfModel(const 
uno::Reference<frame::XModel>& xModel)
 {
-    uno::Reference<frame::XModel> xModel = GetBaseModel();
     if (!xModel.is())
     {
-        return uno::Reference<security::XCertificate>();
+        return uno::Reference<beans::XPropertySet>();
     }
 
     uno::Reference<drawing::XShapes> xShapes(xModel->getCurrentSelection(), 
uno::UNO_QUERY);
     if (!xShapes.is() || xShapes->getCount() < 1)
     {
-        return uno::Reference<security::XCertificate>();
+        return uno::Reference<beans::XPropertySet>();
     }
 
     uno::Reference<beans::XPropertySet> xShapeProps(xShapes->getByIndex(0), 
uno::UNO_QUERY);
-    if (!xShapeProps.is())
+    return xShapeProps;
+}
+}
+
+uno::Reference<security::XCertificate> SfxObjectShell::GetSignPDFCertificate() 
const
+{
+    uno::Reference<beans::XPropertySet> xShapeProps = 
GetSelectedShapeOfModel(GetBaseModel());
+    if (!xShapeProps.is() || 
!xShapeProps->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
     {
         return uno::Reference<security::XCertificate>();
     }
 
-    if 
(!xShapeProps->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
+    comphelper::SequenceAsHashMap 
aMap(xShapeProps->getPropertyValue("InteropGrabBag"));
+    auto it = aMap.find("SignatureCertificate");
+    if (it == aMap.end())
     {
         return uno::Reference<security::XCertificate>();
     }
 
+    return uno::Reference<security::XCertificate>(it->second, uno::UNO_QUERY);
+}
+
+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 uno::Reference<security::XCertificate>();
+        return;
     }
 
-    return uno::Reference<security::XCertificate>(it->second, uno::UNO_QUERY);
+    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(ErrCodeMsg error)
@@ -595,26 +619,15 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
                 aSigningContext.m_xCertificate = xCertificate;
                 bHaveWeSigned |= 
SignDocumentContentUsingCertificate(aSigningContext);
 
-                // Reload to show how the PDF actually looks like after 
signing. This also
-                // changes "finish signing" on the infobar back to "sign 
document" as a side
-                // effect.
+                // 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())
                 {
-                    // Store current page before reload.
-                    SfxAllItemSet aSet(SfxGetpApp()->GetPool());
-                    uno::Reference<drawing::XDrawView> xController(
-                        GetBaseModel()->getCurrentController(), 
uno::UNO_QUERY);
-                    uno::Reference<beans::XPropertySet> 
xPage(xController->getCurrentPage(),
-                                                              uno::UNO_QUERY);
-                    sal_Int32 nPage{};
-                    xPage->getPropertyValue("Number") >>= nPage;
-                    if (nPage > 0)
-                    {
-                        // nPage is 1-based.
-                        aSet.Put(SfxInt32Item(SID_PAGE_NUMBER, nPage - 1));
-                    }
-                    SfxRequest aReq(SID_RELOAD, SfxCallMode::SLOT, aSet);
-                    pFrame->ExecReload_Impl(aReq);
+                    ResetSignPDFCertificate();
+                    RecheckSignature(false);
+                    pFrame->RemoveInfoBar(u"readonly");
+                    pFrame->AppendReadOnlyInfobar();
                 }
             }
             else
@@ -2253,6 +2266,13 @@ bool 
SfxObjectShell::SignDocumentContentUsingCertificate(svl::crypto::SigningCon
     // the document is not new and is not modified
     OUString 
aODFVersion(comphelper::OStorageHelper::GetODFVersionFromStorage(GetStorage()));
 
+    if (IsModified() && IsSignPDF())
+    {
+        // When signing a PDF, then adding/resizing/moving the signature line 
would nominally modify
+        // the document, but ignore that for signing.
+        SetModified(false);
+    }
+
     if (IsModified() || !GetMedium() || GetMedium()->GetName().isEmpty()
       || (GetMedium()->GetFilter()->IsOwnFormat() && 
aODFVersion.compareTo(ODFVER_012_TEXT) < 0 && !bHasSign))
     {

Reply via email to