include/sfx2/digitalsignatures.hxx                         |    5 +
 officecfg/registry/schema/org/openoffice/Office/Common.xcs |    7 +
 sfx2/source/doc/docfile.cxx                                |   32 ++++++
 xmlsecurity/inc/UriBindingHelper.hxx                       |   10 +-
 xmlsecurity/inc/digitalsignaturesdialog.hxx                |    2 
 xmlsecurity/inc/documentsignaturemanager.hxx               |    7 +
 xmlsecurity/inc/xmlsignaturehelper.hxx                     |    3 
 xmlsecurity/qa/unit/signing/data/macro.odt                 |binary
 xmlsecurity/qa/unit/signing/signing.cxx                    |   62 +++++++++++++
 xmlsecurity/source/component/documentdigitalsignatures.cxx |   12 ++
 xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx     |   39 +++++++-
 xmlsecurity/source/helper/UriBindingHelper.cxx             |   29 +++++-
 xmlsecurity/source/helper/documentsignaturemanager.cxx     |    9 +
 xmlsecurity/source/helper/xmlsignaturehelper.cxx           |    5 -
 14 files changed, 210 insertions(+), 12 deletions(-)

New commits:
commit a0b779adad4055cfe4f0fa765bb45d6f7d46ef9b
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Sep 12 15:29:33 2024 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri Sep 13 10:50:51 2024 +0200

    cool#9992 lok doc sign: allow sign of macros & the document itself in one 
step
    
    Sign a document with macros (via file -> digital signatures -> digital
    signatures), realize that you still get a warning on file open, sign the
    macros in the document (via tools -> macros -> digital signature),
    realize that you did this in the wrong order, so now you have to re-sign
    the doc content.
    
    The reason for this is that the macro signature only signs the macro
    parts of the document (so you can still edit the document and the
    signature is valid, as long as you don't touch macros), while the doc
    content signature signs everything, including the macro signature, so
    the order of the two matters.
    
    Solve this trouble by adding a new setting that allows doing the two
    signatures in one step. Do this by extending the doc content signing
    code with an optional pre-step that first signs the document macros.
    This is a bit tricky to do, since xmlsecurity/ gets an RW signature
    stream and a RO document storage from sfx2/, but transferring one more
    signature stream can solve this trouble.
    
    Other tricky parts of the change:
    1) The crypto signing is always done by libxmlsec, so
       DigitalSignaturesDialog::SetScriptingSignatureStream() has to update
       the storage of the sign manager's sign helper, otherwise, the hashes in
       the macro signature will be empty.
    2) Signing reads the RO storage, so normally the macro signature
       would not be part of the doc signature when creating both signatures
       inside a single dialog. (The storage is only committed after the
       dialog ends.) Fix this problem by extending
       DocumentSignatureManager::add() and UriBindingHelper::OpenInputStream()
       to provide kind of an overlay when xmlsecurity/ gets a script signature
       stream: this way the macro signature will be part of the doc signature
       while the dialog is in progress. No overlay is needed later, once both
       streams are committed to the storage on dialog end.
    
    (cherry picked from commit e5a0209d4b1e1f09191a442e04d626b21c49b9df)
    
    Conflicts:
            xmlsecurity/inc/xmlsignaturehelper.hxx
    
    Change-Id: Ic2728689997165595991d5ec59c7a2683286e22d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173314
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/include/sfx2/digitalsignatures.hxx 
b/include/sfx2/digitalsignatures.hxx
index b364c9518931..856e1c5bf61a 100644
--- a/include/sfx2/digitalsignatures.hxx
+++ b/include/sfx2/digitalsignatures.hxx
@@ -45,6 +45,11 @@ public:
                               const std::function<void(bool)>& rCallback)
         = 0;
 
+    /// Create a scripting signature before creating a document signature.
+    virtual void
+    SetSignScriptingContent(const css::uno::Reference<css::io::XStream>& 
xScriptingSignStream)
+        = 0;
+
 protected:
     ~DigitalSignatures() noexcept = default;
 };
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs 
b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index 4c4826e97904..aa8bca5cee00 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -2370,6 +2370,13 @@
           </info>
           <value>true</value>
         </prop>
+        <prop oor:name="ImplicitScriptSign" oor:type="xs:boolean" 
oor:nillable="false">
+          <info>
+            <desc>Specifies whether to implicitly sign macros when adding the 
first signature
+            to an ODF document with macros.</desc>
+          </info>
+          <value>false</value>
+        </prop>
         <prop oor:name="CertDir" oor:type="xs:string">
           <info>
             <desc>Contains the path to the users NSS certificate 
directory.</desc>
diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
index 44edea053a8c..8002645a015a 100644
--- a/sfx2/source/doc/docfile.cxx
+++ b/sfx2/source/doc/docfile.cxx
@@ -4433,12 +4433,39 @@ void SfxMedium::SignContents_Impl(weld::Window* 
pDialogParent,
         }
         else
         {
+            // Signing the entire document.
             if (xMetaInf.is())
             {
                 // ODF.
                 uno::Reference< io::XStream > xStream;
+                uno::Reference< io::XStream > xScriptingStream;
                 if (GetFilter() && GetFilter()->IsOwnFormat())
+                {
+                    bool bImplicitScriptSign = 
officecfg::Office::Common::Security::Scripting::ImplicitScriptSign::get();
+                    if (comphelper::LibreOfficeKit::isActive())
+                    {
+                        bImplicitScriptSign = true;
+                    }
+
+                    OUString aDocSigName = 
xSigner->getDocumentContentSignatureDefaultStreamName();
+                    bool bHasSignatures = xMetaInf->hasByName(aDocSigName);
+
+                    // C.f. DocumentSignatureHelper::CreateElementList() for 
the
+                    // DocumentSignatureMode::Macros case.
+                    bool bHasMacros = 
xWriteableZipStor->hasByName(u"Basic"_ustr)
+                                      || 
xWriteableZipStor->hasByName(u"Dialogs"_ustr)
+                                      || 
xWriteableZipStor->hasByName(u"Scripts"_ustr);
+
                     
xStream.set(xMetaInf->openStreamElement(xSigner->getDocumentContentSignatureDefaultStreamName(),
 embed::ElementModes::READWRITE), uno::UNO_SET_THROW);
+                    if (bImplicitScriptSign && bHasMacros && !bHasSignatures)
+                    {
+                        xScriptingStream.set(
+                            xMetaInf->openStreamElement(
+                                
xSigner->getScriptingContentSignatureDefaultStreamName(),
+                                embed::ElementModes::READWRITE),
+                            uno::UNO_SET_THROW);
+                    }
+                }
 
                 bool bSuccess = false;
                 auto onODFSignDocumentContentFinished = [this, xMetaInf, 
xWriteableZipStor]() {
@@ -4456,6 +4483,11 @@ void SfxMedium::SignContents_Impl(weld::Window* 
pDialogParent,
                         xValidGraphic, xInvalidGraphic, aComment);
                 else
                 {
+                    if (xScriptingStream.is())
+                    {
+                        
xModelSigner->SetSignScriptingContent(xScriptingStream);
+                    }
+
                     // Async, all code before return has to go into the 
callback.
                     
xModelSigner->SignDocumentContentAsync(GetZipStorageToSign_Impl(),
                                                             xStream, 
[onODFSignDocumentContentFinished, onSignDocumentContentFinished](bool bRet) {
diff --git a/xmlsecurity/inc/UriBindingHelper.hxx 
b/xmlsecurity/inc/UriBindingHelper.hxx
index 67c9ae69f8ba..f8a07d4d4264 100644
--- a/xmlsecurity/inc/UriBindingHelper.hxx
+++ b/xmlsecurity/inc/UriBindingHelper.hxx
@@ -26,7 +26,10 @@
 #include <com/sun/star/xml/crypto/XUriBinding.hpp>
 
 namespace com::sun::star {
-    namespace io { class XInputStream; }
+    namespace io {
+        class XStream;
+        class XInputStream;
+    }
     namespace embed { class XStorage; }
 }
 
@@ -36,16 +39,17 @@ class UriBindingHelper final : public cppu::WeakImplHelper< 
css::xml::crypto::XU
 {
 private:
     css::uno::Reference < css::embed::XStorage > mxStorage;
+    css::uno::Reference<css::io::XStream> mxScriptingSignatureStream;
 
 public:
     UriBindingHelper();
-    explicit UriBindingHelper( const css::uno::Reference < 
css::embed::XStorage >& rxStorage );
+    explicit UriBindingHelper( const css::uno::Reference < 
css::embed::XStorage >& rxStorage, const css::uno::Reference<css::io::XStream>& 
xScriptingSignatureStream );
 
     void SAL_CALL setUriBinding( const OUString& uri, const 
css::uno::Reference< css::io::XInputStream >& aInputStream ) override;
 
     css::uno::Reference< css::io::XInputStream > SAL_CALL getUriBinding( const 
OUString& uri ) override;
 
-    static css::uno::Reference < css::io::XInputStream > OpenInputStream( 
const css::uno::Reference < css::embed::XStorage >& rxStore, const OUString& 
rURI );
+    static css::uno::Reference < css::io::XInputStream > OpenInputStream( 
const css::uno::Reference < css::embed::XStorage >& rxStore, const OUString& 
rURI, const css::uno::Reference<css::io::XStream>& xScriptingSignatureStream );
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/digitalsignaturesdialog.hxx 
b/xmlsecurity/inc/digitalsignaturesdialog.hxx
index 08db226fb8a8..375328d91a88 100644
--- a/xmlsecurity/inc/digitalsignaturesdialog.hxx
+++ b/xmlsecurity/inc/digitalsignaturesdialog.hxx
@@ -43,6 +43,7 @@ class DigitalSignaturesDialog final : public 
weld::GenericDialogController
 {
 private:
     DocumentSignatureManager maSignatureManager;
+    std::optional<DocumentSignatureManager> moScriptSignatureManager;
     bool                    mbVerifySignatures;
     bool                    mbSignaturesChanged;
 
@@ -112,6 +113,7 @@ public:
             // Set the storage which should be signed or verified
     void    SetStorage( const css::uno::Reference < css::embed::XStorage >& 
rxStore );
     void    SetSignatureStream( const css::uno::Reference < css::io::XStream 
>& rxStream );
+    void    SetScriptingSignatureStream( const css::uno::Reference < 
css::io::XStream >& rxStream );
 
     // Execute the dialog...
     void    beforeRun();
diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx 
b/xmlsecurity/inc/documentsignaturemanager.hxx
index 9f0c5d61f9e2..a66d97e3c7dd 100644
--- a/xmlsecurity/inc/documentsignaturemanager.hxx
+++ b/xmlsecurity/inc/documentsignaturemanager.hxx
@@ -68,6 +68,7 @@ private:
     DocumentSignatureMode const meSignatureMode;
     css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>> 
m_manifest;
     css::uno::Reference<css::io::XStream> mxSignatureStream;
+    css::uno::Reference<css::io::XStream> mxScriptingSignatureStream;
     css::uno::Reference<css::frame::XModel> mxModel;
     rtl::Reference<utl::TempFileFastService> mxTempSignatureStream;
     /// Storage containing all OOXML signatures, unused for ODF.
@@ -126,6 +127,12 @@ public:
     {
         mxSignatureStream = xSignatureStream;
     }
+    css::uno::Reference<css::io::XStream> getSignatureStream() const { return 
mxSignatureStream; }
+    void setScriptingSignatureStream(
+        const css::uno::Reference<css::io::XStream>& xScriptingSignatureStream)
+    {
+        mxScriptingSignatureStream = xScriptingSignatureStream;
+    }
     void setModel(const css::uno::Reference<css::frame::XModel>& xModel);
     const css::uno::Reference<css::embed::XStorage>& getStore() const { return 
mxStore; }
     DocumentSignatureMode getSignatureMode() const { return meSignatureMode; }
diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx 
b/xmlsecurity/inc/xmlsignaturehelper.hxx
index d6e2b90eebac..94bc309c5436 100644
--- a/xmlsecurity/inc/xmlsignaturehelper.hxx
+++ b/xmlsecurity/inc/xmlsignaturehelper.hxx
@@ -37,6 +37,7 @@ namespace com::sun::star {
     namespace io {
         class XOutputStream;
         class XInputStream;
+        class XStream;
     }
     namespace embed { class XStorage; }
 }
@@ -83,7 +84,7 @@ public:
     // Set the storage which should be used by the default UriBinding
     // Must be set before StartMission().
     //sODFVersion indicates  the ODF version
-    void        SetStorage( const css::uno::Reference < css::embed::XStorage 
>& rxStorage, std::u16string_view sODFVersion );
+    void        SetStorage( const css::uno::Reference < css::embed::XStorage 
>& rxStorage, std::u16string_view sODFVersion, const 
css::uno::Reference<css::io::XStream>& xScriptStream = 
css::uno::Reference<css::io::XStream>() );
 
                 // Argument for the Link is a uno::Reference< 
xml::sax::XAttributeList >*
                 // Return 1 to verify, 0 to skip.
diff --git a/xmlsecurity/qa/unit/signing/data/macro.odt 
b/xmlsecurity/qa/unit/signing/data/macro.odt
new file mode 100644
index 000000000000..b6e470076bef
Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/macro.odt differ
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index 316eaf22f5b7..a853de5e9367 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -1145,6 +1145,68 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testSignatureLineODF)
     CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is());
 }
 
+CPPUNIT_TEST_FIXTURE(SigningTest, testImplicitScriptSign)
+{
+    // Given an ODT file with macros, and two signature managers to create 
macro + doc signatures:
+    OUString aFileURL = createFileURL(u"macro.odt");
+    uno::Reference<embed::XStorage> xWriteableZipStor
+        = 
comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING,
 aFileURL,
+                                                                
embed::ElementModes::READWRITE);
+    uno::Reference<embed::XStorage> xMetaInf
+        = xWriteableZipStor->openStorageElement(u"META-INF"_ustr, 
embed::ElementModes::READWRITE);
+    uno::Reference<io::XStream> xStream = xMetaInf->openStreamElement(
+        u"documentsignatures.xml"_ustr, embed::ElementModes::READWRITE);
+    uno::Reference<io::XStream> xScriptingStream
+        = xMetaInf->openStreamElement(u"macrosignatures.xml"_ustr, 
embed::ElementModes::READWRITE);
+    uno::Reference<embed::XStorage> xZipStor
+        = 
comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING,
 aFileURL,
+                                                                
embed::ElementModes::READ);
+    DocumentSignatureManager aManager(m_xContext, 
DocumentSignatureMode::Content);
+    CPPUNIT_ASSERT(aManager.init());
+    aManager.setStore(xZipStor);
+    aManager.setSignatureStream(xStream);
+    aManager.getSignatureHelper().SetStorage(xZipStor, u"1.2", 
xScriptingStream);
+    DocumentSignatureManager aScriptManager(m_xContext, 
DocumentSignatureMode::Macros);
+    CPPUNIT_ASSERT(aScriptManager.init());
+    aScriptManager.setStore(xZipStor);
+    aScriptManager.getSignatureHelper().SetStorage(xZipStor, u"1.2");
+    aScriptManager.setSignatureStream(xScriptingStream);
+    uno::Reference<security::XCertificate> xCertificate
+        = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
+    if (!xCertificate.is())
+        return;
+
+    // When adding those signatures and writing them to the streams from the 
read-write storage:
+    OUString aDescription;
+    sal_Int32 nSecurityId;
+    bool bAdESCompliant = true;
+    aScriptManager.add(xCertificate, mxSecurityContext, aDescription, 
nSecurityId, bAdESCompliant);
+    aScriptManager.read(/*bUseTempStream=*/true, 
/*bCacheLastSignature=*/false);
+    aScriptManager.write(bAdESCompliant);
+    aManager.setScriptingSignatureStream(xScriptingStream);
+    aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, 
bAdESCompliant);
+    aManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
+    aManager.write(bAdESCompliant);
+
+    // Then make sure both signatures are created correctly:
+    std::unique_ptr<SvStream> 
pStream(utl::UcbStreamHelper::CreateStream(xScriptingStream, true));
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+    OUString aScriptDigest = getXPathContent(
+        pXmlDoc, 
"/odfds:document-signatures/dsig:Signature[1]/dsig:SignedInfo/"
+                 
"dsig:Reference[@URI='Basic/script-lc.xml']/dsig:DigestValue"_ostr);
+    // Without the accompanying fix in place, this test would have failed, the 
digest value was just a
+    // " " placeholder.
+    CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(1), 
aScriptDigest.getLength());
+    pStream = utl::UcbStreamHelper::CreateStream(xStream, true);
+    pXmlDoc = parseXmlStream(pStream.get());
+    // Without the accompanying fix in place, this test would have failed, the 
macro signature was
+    // not part of the signed data of the document signature.
+    assertXPath(pXmlDoc,
+                "/odfds:document-signatures/dsig:Signature[1]/dsig:SignedInfo/"
+                "dsig:Reference[@URI='META-INF/macrosignatures.xml']"_ostr,
+                1);
+}
+
 #if HAVE_FEATURE_GPGVERIFY
 /// Test a typical ODF where all streams are GPG-signed.
 CPPUNIT_TEST_FIXTURE(SigningTest, testODFGoodGPG)
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx 
b/xmlsecurity/source/component/documentdigitalsignatures.cxx
index 5b491f20a550..d7f2121442d8 100644
--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx
+++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
@@ -78,6 +78,7 @@ class DocumentDigitalSignatures
 private:
     css::uno::Reference<css::uno::XComponentContext> mxCtx;
     css::uno::Reference<css::awt::XWindow> mxParentWindow;
+    uno::Reference<io::XStream> mxScriptingSignStream;
 
     /// will be set by XInitialization. If not we assume true. false means an 
earlier version (whatever that means,
     /// this is a string, not a boolean).
@@ -226,6 +227,10 @@ public:
     void SignScriptingContentAsync(const 
css::uno::Reference<css::embed::XStorage>& xStorage,
                                    const 
css::uno::Reference<css::io::XStream>& xSignStream,
                                    const std::function<void(bool)>& rCallback) 
override;
+
+    /// See sfx2::DigitalSignatures::SetSignScriptingContent().
+    void SetSignScriptingContent(
+        const css::uno::Reference<css::io::XStream>& xScriptingSignStream) 
override;
 };
 
 }
@@ -449,6 +454,7 @@ void DocumentDigitalSignatures::ImplViewSignatures(
         xSignaturesDialog->SetStorage(rxStorage);
 
         xSignaturesDialog->SetSignatureStream( xSignStream );
+        xSignaturesDialog->SetScriptingSignatureStream( mxScriptingSignStream 
);
 
         xSignaturesDialog->beforeRun();
         weld::DialogController::runAsync(xSignaturesDialog, 
[xSignaturesDialog, rxStorage, xSignStream, rCallback] (sal_Int32 nRet) {
@@ -852,6 +858,12 @@ void DocumentDigitalSignatures::SignScriptingContentAsync(
     ImplViewSignatures( rxStorage, xSignStream, DocumentSignatureMode::Macros, 
false, rCallback );
 }
 
+void DocumentDigitalSignatures::SetSignScriptingContent(
+    const css::uno::Reference<css::io::XStream>& xScriptingSignStream)
+{
+    mxScriptingSignStream = xScriptingSignStream;
+}
+
 sal_Bool DocumentDigitalSignatures::signPackageWithCertificate(
     css::uno::Reference<css::security::XCertificate> const& xCertificate,
     css::uno::Reference<css::embed::XStorage> const& xStorage,
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx 
b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index 8349a58a31ce..6fef60f01194 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -354,7 +354,7 @@ void DigitalSignaturesDialog::SetStorage( const 
css::uno::Reference < css::embed
                     || !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
 
     maSignatureManager.setStore(rxStore);
-    maSignatureManager.getSignatureHelper().SetStorage( 
maSignatureManager.getStore(), m_sODFVersion);
+    maSignatureManager.getSignatureHelper().SetStorage( 
maSignatureManager.getStore(), m_sODFVersion, {});
 }
 
 void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < 
css::io::XStream >& rxStream )
@@ -362,6 +362,26 @@ void DigitalSignaturesDialog::SetSignatureStream( const 
css::uno::Reference < cs
     maSignatureManager.setSignatureStream(rxStream);
 }
 
+void DigitalSignaturesDialog::SetScriptingSignatureStream( const 
css::uno::Reference < css::io::XStream >& rxStream )
+{
+    if (!rxStream.is())
+    {
+        return;
+    }
+
+    uno::Reference<uno::XComponentContext> xContext = 
comphelper::getProcessComponentContext();
+    moScriptSignatureManager.emplace(xContext, DocumentSignatureMode::Macros);
+    if (!moScriptSignatureManager->init())
+    {
+        return;
+    }
+    moScriptSignatureManager->setStore(maSignatureManager.getStore());
+    // This is the storage used by UriBindingHelper::getUriBinding().
+    
moScriptSignatureManager->getSignatureHelper().SetStorage(maSignatureManager.getStore(),
 m_sODFVersion);
+    
maSignatureManager.getSignatureHelper().SetStorage(maSignatureManager.getStore(),
 m_sODFVersion, rxStream);
+    moScriptSignatureManager->setSignatureStream(rxStream);
+}
+
 bool DigitalSignaturesDialog::canAddRemove()
 {
     //FIXME: this func needs some cleanup, such as real split between
@@ -513,6 +533,23 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, 
weld::Button&, void)
         if (aChooser->run() == RET_OK)
         {
             sal_Int32 nSecurityId;
+
+            if (moScriptSignatureManager)
+            {
+                if 
(!moScriptSignatureManager->add(aChooser->GetSelectedCertificates()[0],
+                                                   
aChooser->GetSelectedSecurityContext(),
+                                                   aChooser->GetDescription(), 
nSecurityId,
+                                                   m_bAdESCompliant))
+                {
+                    return;
+                }
+
+                moScriptSignatureManager->read(/*bUseTempStream=*/true, 
/*bCacheLastSignature=*/false);
+                moScriptSignatureManager->write(m_bAdESCompliant);
+
+                
maSignatureManager.setScriptingSignatureStream(moScriptSignatureManager->getSignatureStream());
+            }
+
             if 
(!maSignatureManager.add(aChooser->GetSelectedCertificates()[0], 
aChooser->GetSelectedSecurityContext(),
                                         aChooser->GetDescription(), 
nSecurityId, m_bAdESCompliant))
                 return;
diff --git a/xmlsecurity/source/helper/UriBindingHelper.cxx 
b/xmlsecurity/source/helper/UriBindingHelper.cxx
index f6c36d2c8b36..4aabca28310f 100644
--- a/xmlsecurity/source/helper/UriBindingHelper.cxx
+++ b/xmlsecurity/source/helper/UriBindingHelper.cxx
@@ -28,6 +28,8 @@
 #include <rtl/uri.hxx>
 #include <sal/log.hxx>
 
+#include <documentsignaturehelper.hxx>
+
 using namespace com::sun::star;
 
 // XUriBinding
@@ -36,9 +38,10 @@ UriBindingHelper::UriBindingHelper()
 {
 }
 
-UriBindingHelper::UriBindingHelper( const css::uno::Reference < 
css::embed::XStorage >& rxStorage )
+UriBindingHelper::UriBindingHelper( const css::uno::Reference < 
css::embed::XStorage >& rxStorage, const uno::Reference<io::XStream>& 
xScriptingSignatureStream )
 {
     mxStorage = rxStorage;
+    mxScriptingSignatureStream = xScriptingSignatureStream;
 }
 
 void SAL_CALL UriBindingHelper::setUriBinding( const OUString& /*uri*/, const 
uno::Reference< io::XInputStream >&)
@@ -50,7 +53,7 @@ uno::Reference< io::XInputStream > SAL_CALL 
UriBindingHelper::getUriBinding( con
     uno::Reference< io::XInputStream > xInputStream;
     if ( mxStorage.is() )
     {
-        xInputStream = OpenInputStream( mxStorage, uri );
+        xInputStream = OpenInputStream( mxStorage, uri, 
mxScriptingSignatureStream );
     }
     else
     {
@@ -62,7 +65,7 @@ uno::Reference< io::XInputStream > SAL_CALL 
UriBindingHelper::getUriBinding( con
     return xInputStream;
 }
 
-uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const 
uno::Reference < embed::XStorage >& rxStore, const OUString& rURI )
+uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const 
uno::Reference < embed::XStorage >& rxStore, const OUString& rURI, const 
css::uno::Reference<css::io::XStream>& xScriptingSignatureStream )
 {
     OSL_ASSERT(!rURI.isEmpty());
     uno::Reference < io::XInputStream > xInStream;
@@ -89,7 +92,23 @@ uno::Reference < io::XInputStream > 
UriBindingHelper::OpenInputStream( const uno
 
         uno::Reference< io::XStream > xStream;
         if (!rxStore->hasByName(sName))
-            SAL_WARN("xmlsecurity.helper", "expected stream, but not found: " 
<< sName);
+        {
+            if (xScriptingSignatureStream.is() && sName == 
DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName())
+            {
+                xStream = xScriptingSignatureStream;
+                uno::Reference<io::XSeekable> 
xSeekable(xScriptingSignatureStream, uno::UNO_QUERY);
+                if (xSeekable.is())
+                {
+                    // Cloned streams are always positioned at the start, do 
the same in the overlay
+                    // case.
+                    xSeekable->seek(0);
+                }
+            }
+            else
+            {
+                SAL_WARN("xmlsecurity.helper", "expected stream, but not 
found: " << sName);
+            }
+        }
         else
             xStream = rxStore->cloneStreamElement( sName );
         if ( !xStream.is() )
@@ -105,7 +124,7 @@ uno::Reference < io::XInputStream > 
UriBindingHelper::OpenInputStream( const uno
 
         OUString aElement = aURI.copy( nSepPos+1 );
         uno::Reference < embed::XStorage > xSubStore = 
rxStore->openStorageElement( aStoreName, embed::ElementModes::READ );
-        xInStream = OpenInputStream( xSubStore, aElement );
+        xInStream = OpenInputStream( xSubStore, aElement, 
xScriptingSignatureStream );
     }
     return xInStream;
 }
diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx 
b/xmlsecurity/source/helper/documentsignaturemanager.cxx
index 0bc34dcd379b..9ed1cef7dcff 100644
--- a/xmlsecurity/source/helper/documentsignaturemanager.cxx
+++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx
@@ -435,6 +435,15 @@ bool DocumentSignatureManager::add(
 
     std::vector<OUString> aElements = 
DocumentSignatureHelper::CreateElementList(
         mxStore, meSignatureMode, DocumentSignatureAlgorithm::OOo3_2);
+
+    if (mxScriptingSignatureStream.is())
+    {
+        aElements.emplace_back(
+            u"META-INF/"_ustr
+            + 
DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName());
+        std::sort(aElements.begin(), aElements.end());
+    }
+
     DocumentSignatureHelper::AppendContentTypes(mxStore, aElements);
 
     for (OUString const& rUri : aElements)
diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx 
b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
index 3b13f79f33f1..6620e33b47a7 100644
--- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx
+++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
@@ -71,10 +71,11 @@ XMLSignatureHelper::~XMLSignatureHelper()
 
 void XMLSignatureHelper::SetStorage(
     const Reference < css::embed::XStorage >& rxStorage,
-    std::u16string_view sODFVersion)
+    std::u16string_view sODFVersion,
+    const css::uno::Reference<css::io::XStream>& xScriptStream)
 {
     SAL_WARN_IF( mxUriBinding.is(), "xmlsecurity.helper", "SetStorage - 
UriBinding already set!" );
-    mxUriBinding = new UriBindingHelper( rxStorage );
+    mxUriBinding = new UriBindingHelper( rxStorage, xScriptStream );
     SAL_WARN_IF(!rxStorage.is(), "xmlsecurity.helper", "SetStorage - empty 
storage!");
     mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(sODFVersion);
 }

Reply via email to