filter/qa/data/ca.pem                  |   70 +++++++++++++++++++++++++++++++++
 filter/qa/data/cert.pem                |   31 ++++++++++++++
 filter/qa/data/key.pem                 |   28 +++++++++++++
 filter/qa/pdf.cxx                      |   60 ++++++++++++++++++++++++++++
 filter/source/pdf/pdfexport.cxx        |   28 +++++++++++++
 sc/inc/queryevaluator.hxx              |    2 
 sc/source/core/data/queryevaluator.cxx |   24 ++++-------
 7 files changed, 228 insertions(+), 15 deletions(-)

New commits:
commit e5a6cb358905b92ea09ccaf745c40b774d53d38e
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Fri Oct 25 11:12:24 2024 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri Oct 25 17:01:38 2024 +0200

    we can remove a SharedString copy now
    
    given that there is no OUString* pValueSource2 case
    
    Change-Id: I5420ebf7cc7cd5d0b77256788e8ecd74d445a286
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175638
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sc/inc/queryevaluator.hxx b/sc/inc/queryevaluator.hxx
index f5817820d4fe..79e9c7b09373 100644
--- a/sc/inc/queryevaluator.hxx
+++ b/sc/inc/queryevaluator.hxx
@@ -93,7 +93,7 @@ class ScQueryEvaluator
     template <bool bFast = false>
     std::pair<bool, bool> compareByString(const ScQueryEntry& rEntry,
                                           const ScQueryEntry::Item& rItem,
-                                          const svl::SharedString* 
pValueSource1);
+                                          const svl::SharedString& 
rValueSource);
     std::pair<bool, bool> compareByTextColor(SCCOL nCol, SCROW nRow,
                                              const ScQueryEntry::Item& rItem);
     std::pair<bool, bool> compareByBackgroundColor(SCCOL nCol, SCROW nRow,
diff --git a/sc/source/core/data/queryevaluator.cxx 
b/sc/source/core/data/queryevaluator.cxx
index 89d2d38d2bd4..cc1da17de152 100644
--- a/sc/source/core/data/queryevaluator.cxx
+++ b/sc/source/core/data/queryevaluator.cxx
@@ -370,12 +370,12 @@ bool ScQueryEvaluator::isFastCompareByString(const 
ScQueryEntry& rEntry) const
            && isMatchWholeCell(rEntry.eOp);
 }
 
-// The value is placed inside one parameter: [pValueSource1].
+// The value is placed inside parameter rValueSource.
 // For the template argument see isFastCompareByString().
 template <bool bFast>
 std::pair<bool, bool> ScQueryEvaluator::compareByString(const ScQueryEntry& 
rEntry,
                                                         const 
ScQueryEntry::Item& rItem,
-                                                        const 
svl::SharedString* pValueSource1)
+                                                        const 
svl::SharedString& rValueSource)
 {
     bool bOk = false;
     bool bTestEqual = false;
@@ -387,11 +387,9 @@ std::pair<bool, bool> 
ScQueryEvaluator::compareByString(const ScQueryEntry& rEnt
     const bool bRealWildOrRegExp = !bFast && isRealWildOrRegExp(rEntry);
     const bool bTestWildOrRegExp = !bFast && isTestWildOrRegExp(rEntry);
 
-    assert(pValueSource1);
-
     if (!bFast && (bRealWildOrRegExp || bTestWildOrRegExp))
     {
-        const OUString& rValue = pValueSource1->getString();
+        const OUString& rValue = rValueSource.getString();
 
         sal_Int32 nStart = 0;
         sal_Int32 nEnd = rValue.getLength();
@@ -467,11 +465,11 @@ std::pair<bool, bool> 
ScQueryEvaluator::compareByString(const ScQueryEntry& rEnt
                 // This is the bFast path, all conditions should lead here on 
bFast == true.
                 if (mrParam.bCaseSens)
                 {
-                    bOk = pValueSource1->getData() == rItem.maString.getData();
+                    bOk = rValueSource.getData() == rItem.maString.getData();
                 }
                 else
                 {
-                    bOk = pValueSource1->getDataIgnoreCase() == 
rItem.maString.getDataIgnoreCase();
+                    bOk = rValueSource.getDataIgnoreCase() == 
rItem.maString.getDataIgnoreCase();
                 }
 
                 if (!bFast && rEntry.eOp == SC_NOT_EQUAL)
@@ -484,10 +482,8 @@ std::pair<bool, bool> 
ScQueryEvaluator::compareByString(const ScQueryEntry& rEnt
 
                 if (!mbCaseSensitive)
                 { // Common case for vlookup etc.
-                    const svl::SharedString rSource(*pValueSource1);
-
                     const rtl_uString* pQuer = 
rItem.maString.getDataIgnoreCase();
-                    const rtl_uString* pCellStr = rSource.getDataIgnoreCase();
+                    const rtl_uString* pCellStr = 
rValueSource.getDataIgnoreCase();
 
                     assert(pCellStr != nullptr);
                     if (pQuer == nullptr)
@@ -512,7 +508,7 @@ std::pair<bool, bool> 
ScQueryEvaluator::compareByString(const ScQueryEntry& rEnt
                 }
                 else
                 {
-                    const OUString& rValue = pValueSource1->getString();
+                    const OUString& rValue = rValueSource.getString();
                     const OUString aQueryStr = rItem.maString.getString();
                     const LanguageType nLang
                         = 
ScGlobal::oSysLocale->GetLanguageTag().getLanguageType();
@@ -559,7 +555,7 @@ std::pair<bool, bool> 
ScQueryEvaluator::compareByString(const ScQueryEntry& rEnt
         }
         else
         { // use collator here because data was probably sorted
-            const OUString& rValue = pValueSource1->getString();
+            const OUString& rValue = rValueSource.getString();
             setupCollatorIfNeeded();
             sal_Int32 nCompare = mpCollator->compareString(rValue, 
rItem.maString.getString());
             switch (rEntry.eOp)
@@ -794,9 +790,9 @@ std::pair<bool, bool> ScQueryEvaluator::processEntry(SCROW 
nRow, SCCOL nCol, ScR
             svl::SharedString cellSharedString = getCellSharedString(aCell, 
nRow, rEntry.nField);
             std::pair<bool, bool> aThisRes;
             if (bFastCompareByString) // fast
-                aThisRes = compareByString<true>(rEntry, rItem, 
&cellSharedString);
+                aThisRes = compareByString<true>(rEntry, rItem, 
cellSharedString);
             else
-                aThisRes = compareByString(rEntry, rItem, &cellSharedString);
+                aThisRes = compareByString(rEntry, rItem, cellSharedString);
             aRes.first |= aThisRes.first;
             aRes.second |= aThisRes.second;
         }
commit 1e75155c6995e4f1534e2062c64fab35d49ea60b
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Oct 25 10:43:51 2024 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Oct 25 17:01:33 2024 +0200

    cool#9992 lok doc sign: allow injecting sign cert/key during pdf export
    
    Interactive signing via the .uno:Signature command parameters were
    possible, but headless PDF export had no similar parameters.
    
    The primary difference is that the interactive signing works with the
    sign certificate of the SfxViewShell, while PDF export has its own
    vcl::PDFWriter::PDFWriterContext::SignCertificate.
    
    Fix the problem similar to what commit
    80723fccbb03c215bab84b10ac1eefaedef66b7c (filter: allow PDF export to
    sign from the cmdline, 2022-02-03) did, but here we don't refer to an
    already configured sign certificate by name, we take the sign cert/key
    from parameters instead.
    
    Test this in the NSS case where it's known to work, ignore the mscng
    signing case for now.
    
    Change-Id: Ib0c171736d2554fb3678ae4b8842541c43f9f3dd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175644
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/filter/qa/data/ca.pem b/filter/qa/data/ca.pem
new file mode 100644
index 000000000000..d08c9c67bcae
--- /dev/null
+++ b/filter/qa/data/ca.pem
@@ -0,0 +1,70 @@
+-----BEGIN CERTIFICATE-----
+MIIGADCCA+igAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVL
+MRAwDgYDVQQIDAdFbmdsYW5kMTAwLgYDVQQKDCdDcHB1bml0VGVzdF94bWxzZWN1
+cml0eV94bWxzZWMgUlNBIFRlc3QxODA2BgNVBAMML0NwcHVuaXRUZXN0X3htbHNl
+Y3VyaXR5X3htbHNlYyBSU0EgVGVzdCBSb290IENBMCAXDTI0MDkyMzEzMzA0MloY
+DzIxMjQwODMwMTMzMDQyWjCBjzELMAkGA1UEBhMCVUsxEDAOBgNVBAgMB0VuZ2xh
+bmQxMDAuBgNVBAoMJ0NwcHVuaXRUZXN0X3htbHNlY3VyaXR5X3htbHNlYyBSU0Eg
+VGVzdDE8MDoGA1UEAwwzQ3BwdW5pdFRlc3RfeG1sc2VjdXJpdHlfeG1sc2VjIElu
+dGVybWVkaWF0ZSBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
+AgEAj9kribqN994fmGGnL7l3Y4DEVEBUBV2kNlq9fM9wJmOEtaNyKIjYxzCFUAnt
+vKp0youu3tu48duDUez4I+Nc4gyez6IlyfPCXiEJulo0g6F3WZZg/xtk56JZnHFe
+aBHq3vm3L7a5y8c9j9Y26/BPRAqY1CtBSFUWV1uGPCQkNGNsO7qqtOdcKn7dFJq3
+K2sRaXp4J3QUhtlsEQ4/sWtXjuV7f4wqep0PEjFJ8oF6Jao5QYFHuLx4YZmo9vfX
+NSjv1TJbdQ+1zvw8sr3/SYyNt3B7Q3jXq8IC+Tfc1R9t/FaDeS9AiMuDJgq+aHWV
+ej8sspl2+d7mFXCuOoy9nE9aCWAwD1v6Ce1nK97qVUKRKxBxlKSM3TULWaJT8VC9
+UK0nsfK9OocCeybOa+irzVcgvVDlD8fPoM82bGAaA5z2SvSyrjk5/h2aHtG9U1tJ
+ke6GwxzyVlIySo4EC9SvW8Pu3v0vaHAeDAjUnA8aEPGmuKOMHsYq/Jgy3hkRLKuX
+iRENrshP/q0Vfso2NtfErSzqcBV5UWcYUhoCOiQXRo2Q9sy7lJDtRU5yFxlGtqRU
+ORY1LI9NMXi5pJioZftPZIMPJeDLeaEaNHD1vH9i/e/bN11/mYzM2SWuKdQbiYFX
+pZO8gDkp960R1VG3O0TKz7U678ZrjY0Y3t0uNhPFEOZgoCkCAwEAAaNmMGQwHQYD
+VR0OBBYEFFE6wan2eGv91MRbH6vbE4W3cMYNMB8GA1UdIwQYMBaAFOJn33YP7tq0
+45qRr2pHFpbwKe+7MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG
+MA0GCSqGSIb3DQEBCwUAA4ICAQAeNJClgszw5HQysHfoDe8YClRt9NI4b2obxRXY
+FGX4TgLNcXGBctOoB0B/kLK6TXSPNJqHQ2+cjm1Ol9vEr4iTuRDRBp1UPp6DycLO
+9moTnlw6IKj4Nq+OJ4NVPAl0FED2KWKW9fKHOSn2kqJ7Vf4owAGf3fSy6opeqLxg
+GlnwmDSuevdbiKUCTOL4XwAfl1YN7Jj+4lEKSQmJB786MUvb9YzCPXEBDPg0uN8w
+Jm/ToiKhN53rpXLToYAidJBJ1TyqKb0i9ohETrgiBHgLI5evd+5YrhEjkKdSsK4T
+qiodkiUb5UIEcw21D5M/kjimKQrOKWahOKZCjh3xkkRsJyaeoBetZyW79d6JvB5j
+sifp86HQPtohHo8XM6cEXhhQhwAbIoiD4JPoTtQefTvpBCVlh2RIMYgeSKSq/y3E
+aoWEt8OinvZw+JhJbK7oNNPsglIJtax8Jqdc3C4PTFrIA1PnWmr/+EbdMcwnYJjn
+uyUlSajOmTL50XBHJ4krgNTOCjS42obZ4/W7Z/INVhthqIy33fEq8CKaKKytCjDN
+wkZ6dqmMg/9+X/+ClWlr+Q7EPCUw5aW6Qc95aEv59kgct84wxqTQ2jaGuUv2DxNV
++hy8bsFGwPYc6yqbVm+Eu2ibyw+QV3jYJ3t6HdVJGntgRjeumRB/XuhwVwPaIijp
+jZWvGw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIUf0E/LAmzIuu4Y81pnWRf+XARWkowDQYJKoZIhvcNAQEL
+BQAwgYsxCzAJBgNVBAYTAlVLMRAwDgYDVQQIDAdFbmdsYW5kMTAwLgYDVQQKDCdD
+cHB1bml0VGVzdF94bWxzZWN1cml0eV94bWxzZWMgUlNBIFRlc3QxODA2BgNVBAMM
+L0NwcHVuaXRUZXN0X3htbHNlY3VyaXR5X3htbHNlYyBSU0EgVGVzdCBSb290IENB
+MCAXDTI0MDkyMzEzMzA0MVoYDzIxMjQwODMwMTMzMDQxWjCBizELMAkGA1UEBhMC
+VUsxEDAOBgNVBAgMB0VuZ2xhbmQxMDAuBgNVBAoMJ0NwcHVuaXRUZXN0X3htbHNl
+Y3VyaXR5X3htbHNlYyBSU0EgVGVzdDE4MDYGA1UEAwwvQ3BwdW5pdFRlc3RfeG1s
+c2VjdXJpdHlfeG1sc2VjIFJTQSBUZXN0IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQDICUjHlgDCX741a9qvNgs2ba7nxLwb350hNzu7JbrP
+8R4NUpTgbJwbsxdqPPozXQP2Uos/F5zdLk7ZA5e7tH/sa7ZPbeL6LzSiMvR+Cl4T
+DKisr+C/3ASd3d78kLw0UPNpRyVLirxKT9ht10GYBLAgV9kUtQ9lLejOpHDtRq1q
+8TlX0c3N6tw4T7PWq52Hym4XaTtxJc1g7CHddg4CqsTVXf4HdooMVH5AECD52Uv7
+hjEQgY+hrNEQE7lN6gp3HtxANbZusL4N0kSXAH1N6A1JDw+V0Cd020CUxCOWN/SV
+gX9rV67t+ACbObRNLlSkiGQyaPd2UTlMa1zQbpPQuvxsmtBbh50gIlM5qYuCPT+X
+aI93IbGMRp8be7J2QU2T5nrb0wasVKVzaYcIs/fOBi+EL2t+Jd9a8IPrUkHVdcsx
+WW8Y/WA95s+G4M0/5uVWmaeraBJRUo/suu08v4w0ShGBlVdfPe5iTMQWVLmAAZ16
+icvcgtdCr7nyi3tl2Bv/VFNqi+T7lqyL1i+91sr2Stca4wfRmqE0KiU5npFjxkh4
+sbzpuZAfjCvF3ltIZ9TFlmxQ2edf95CrPfw8u0MjEh2sWflgZwzSAdThEyMEIty4
+ZomCqqJ76Fw2kJwMq++9uTJTVXsepqA/jQg0WgK2Tyz3/2eY99twcldXVXuMc7Ge
+AQIDAQABo2MwYTAdBgNVHQ4EFgQU4mffdg/u2rTjmpGvakcWlvAp77swHwYDVR0j
+BBgwFoAU4mffdg/u2rTjmpGvakcWlvAp77swDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAC4errXBxYjJGtxT+5+VwISk
+4ve5nGna8/SNxt7VB0mREG91gnsu3uJvW05zoU+UUOHaaDvAuox2GGEAq/vKJN5y
+TpgnSYSgzFYxd8N+GqFqE3xwIPa02ntPwwLozF3aph4YcqrtCdPPNIXK5CRopnvQ
+LuUHwFvmz/nkoCPg/VlwFjxNvwGehy5wrhd3zmqd9dga8k3MWA+cVVtNnZld5HZu
+rpHOb3H7SCG+3l/kMdnMQCLvUrbKGSVKX6bOaW+FGm+oTTwLen/HHB21wxfPLySQ
+QDEyR1qGNj7sKgGaWU8334boSSjW3OrnHDLlMBr/XQAMgvHfy43qxOmww47xg685
+HNQYtbHIgVLZ6ou8vgzrjzV+Wpu8H7by2HH/yAHwRqsy2nmVPwkrdmCfSwYfZdAW
++Jzazg4gYVnBE89t8HarOXSiSh/YUS0V6F4koQKVv3b8MzmqO3ldRW2JcktrmZmU
+BYCh5UaK3X+Yyeus1UGrYCl6Yqj5M1JEmYmX/3EVeIcEK+H6Kx9Aeqr1WyJss0GT
+KVA5t+mOZ+SSvF3mFLxTo6ydTLOWA63NGuiLnhU1lbQRkTC0Dq0qenECx2gmG8XG
+FHlVbVsYqiaU6FdkFGzm+Scsl8UwygLV5KP0Y/54X8J6ZSRPHNRvBtRnZoRrjNFM
+wSJZ4vw/iDJO03o31TJ3
+-----END CERTIFICATE-----
diff --git a/filter/qa/data/cert.pem b/filter/qa/data/cert.pem
new file mode 100644
index 000000000000..e5bd58abc2a0
--- /dev/null
+++ b/filter/qa/data/cert.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgY8xCzAJBgNVBAYTAlVL
+MRAwDgYDVQQIDAdFbmdsYW5kMTAwLgYDVQQKDCdDcHB1bml0VGVzdF94bWxzZWN1
+cml0eV94bWxzZWMgUlNBIFRlc3QxPDA6BgNVBAMMM0NwcHVuaXRUZXN0X3htbHNl
+Y3VyaXR5X3htbHNlYyBJbnRlcm1lZGlhdGUgUm9vdCBDQTAgFw0yNDA5MjMxMzMw
+NDJaGA8yMTI0MDgzMDEzMzA0MlowgZExCzAJBgNVBAYTAlVLMRAwDgYDVQQIDAdF
+bmdsYW5kMTAwLgYDVQQKDCdDcHB1bml0VGVzdF94bWxzZWN1cml0eV94bWxzZWMg
+UlNBIFRlc3QxPjA8BgNVBAMMNUNwcHVuaXRUZXN0X3htbHNlY3VyaXR5X3htbHNl
+YyBSU0EgVGVzdCBleGFtcGxlIEFsaWNlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAlSfDFDdlDJv1YY6ANc3RuiGu3oduoDFFJL//l0j52J8btQRQrtp5
+P0OaplTYdLi1hK2cj/XV7KWB+E5p/IwgqNZdOXR+RY1jNkQFiSLdMbkwEoPtaPVh
+DAxfSLyIazSsrERgGOBn6EbomVyc87UrVj6QgwzofDRmPtgOFBlDSfFiqIKfxU4T
+lntLOnFiGLFGcVDSsRA/UQiy9o0bAfaS68IB7FpW9NoLTEgzGE/PzCFkGAmgC5yB
+rvk8/tfCVsx8FeqdZqlBZhrD+sP+rItRRXdSiH52C+XMXqowNxJhPBP4HFv5LVQo
+l9oXK5QXieYrFmMpwTJrkNdFXkm+2iJFAQIDAQABo4HFMIHCMAkGA1UdEwQCMAAw
+EQYJYIZIAYb4QgEBBAQDAgWgMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVy
+YXRlZCBDbGllbnQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFKcwU0F2IER917YAPm5S
+FjaVtYHpMB8GA1UdIwQYMBaAFFE6wan2eGv91MRbH6vbE4W3cMYNMA4GA1UdDwEB
+/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDQYJKoZIhvcN
+AQELBQADggIBABtgvYTKyfIZobgnsrO8PjbQIFdyx5YV0RJ8fshcSzSFSZYN0qbC
+J4U2i84Hx9HvzzFtHHEgJ4ot6VXsfEGqFkf8dvafqi1gAQ4cbIazdHQoELgFKJwL
+U5X/NGl0PQ46/l4vKHKrpAN1TRu7MGE0SwxRYM5KlzibXRL485ck/dzap8qSaxt/
+sSW6YxpttM3umPRL+5Mc+ttJBPYKAwfu/dHkBxGC47E/h2oazNOI2nhLsfbT2YmW
+yJpgt/hnqxB7LtZbnAnaMVEWGdlBp79vU6V0+JSznMmc4t1eX6mUl5tXQF+BSmpw
+f4agwi+uSE9WEXfhChjLfEtEGgK/+/tl012EqY8qt1SdwDDH8usEcrK2iyd14Wgs
+uH3swGqYdBaHnNaAgtuMDlQmJYaq5cKbaTj+PGLr5WU9VIXFSIM03dkyGA13I3ts
+cBpWfh3f89q6YoAqdgwUlCg1OqU4LsfS8n8EKvyM1+zb45JlNxzXpFp+/CwR7I2D
+Tk4QXELeFOl1KU7X9eTftliwAqctRGLCvr2VXA4FbkFhtreCctCQm/FUgIr01YrW
+mhr29Wwaz3DBeymbFXUdYQZqI0OSBBc1bDJkMHftpTBp79EoglKXqMb1/7jcV3bT
+oWXfkHN//B4B2gpv7DxHyP7H6teW/hGuCZeIhYDiL0TR1E68RO1sHRT1
+-----END CERTIFICATE-----
diff --git a/filter/qa/data/key.pem b/filter/qa/data/key.pem
new file mode 100644
index 000000000000..6407bb9ab319
--- /dev/null
+++ b/filter/qa/data/key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCVJ8MUN2UMm/Vh
+joA1zdG6Ia7eh26gMUUkv/+XSPnYnxu1BFCu2nk/Q5qmVNh0uLWErZyP9dXspYH4
+Tmn8jCCo1l05dH5FjWM2RAWJIt0xuTASg+1o9WEMDF9IvIhrNKysRGAY4GfoRuiZ
+XJzztStWPpCDDOh8NGY+2A4UGUNJ8WKogp/FThOWe0s6cWIYsUZxUNKxED9RCLL2
+jRsB9pLrwgHsWlb02gtMSDMYT8/MIWQYCaALnIGu+Tz+18JWzHwV6p1mqUFmGsP6
+w/6si1FFd1KIfnYL5cxeqjA3EmE8E/gcW/ktVCiX2hcrlBeJ5isWYynBMmuQ10Ve
+Sb7aIkUBAgMBAAECggEAANSKkIWiWjAZnRSjRzdkTtN5ZAJd4toK24h+v+wIZV61
+e3n66C4BzHzGDP2wMbJB8wdZjZvmqCxLvGTk+EqUM4Xj0Xwp8DWUQCf3zhuYvrI4
+PbRkok3KO7w7dRvk7FA4A0aHOJi6TdbEFHdVbaIqK9L93FeicTdsQ7aRkZ46UZRu
+YcOc//qIy4nD7O4UXaZoV/WKp2c9KJliED7QqnCGGUQpUsY5zvx6LQwWeXzrgCsT
+am6Hi38/o66Ikel1aMACeq6lGmYqyqNIzHgihuyfcZKoMIYZrLQd2P6aC45H81DS
+gQuMQVZBLDFoUX1ARAvvT8heNB38xPevQBo0uqOvAQKBgQDSdZogxv4c6quIY8xX
+3Bf8H+FKD3v82B++c88IUMGKyqZUp7eJoqivKEWDd/vsxEg3SewnRV2OpYgP2ekz
+seTzVPu877Kv+S/cZFlKYeKDovgCamWeDHR+PSasadk/7pG7izC3Khf9cdzWwgno
+OJKJBKlRwMYAvBNwkK026nTRgQKBgQC1bjimwPjUdtogaIfRqR/9KcShavjMWayh
+1QhH3oYoLIEuzIjd0S+zNSOe35fSslr2ss6NEu0yfERW1q/8HWl2TrNEp2oMn2FO
+Mg6OkwhsTbjWbr/mHae4stXpNIPO8UbuxpNx5qGkmcdAgbOsQJ4m7BERrVQItDsv
+mbNpo4gzgQKBgBVmb+21TlGSay7LNxQYBThV5YqqWGk1cMTk8cBetc9vG8qv4zHT
+oGNvLOJZaPyCWPWGRsUXgJPosRUri1L+W9GCarajiP/rzroSWiH+IhJQl/dm6j5P
+9eiAP1Z4zOZ7U8ZGOQXm+dmDonkT8f3zArN8DduKRpf8h92CWJqk7IwBAoGAa7m7
+V3/i/zxmvbFzW5DhFo+zWejLO4LPVvPHy+ybmcT7G0+EwLhRa0XVFaNLYWZXTn3S
+2L7xKfXRGgK1UawhD4chOFVzSXVk8GoWbJ9u8+eeJWxy8u6OxMMi8iolTT3D0UkF
+CS9YsQRB49JfXZqsjQ3EAMv6xoRFVDkd506bM4ECgYBPN8B6QpENSsVoVGcS/gpR
+hLno9fIvIhABCDoYNTkNT6ILJ8BcU7+lv/zs8UQacqf6Fy7JozbBeEY/Dxr97DKg
+e5djZvWYLqmvAiPilN5YEt5WvuswzrGaTcol/E3X5B3aACFFE8+O9i8T2q0VlAot
+hC+h7nh0KmPyzL73JUX2Jg==
+-----END PRIVATE KEY-----
diff --git a/filter/qa/pdf.cxx b/filter/qa/pdf.cxx
index d9dfc4ef17dd..293d79a46368 100644
--- a/filter/qa/pdf.cxx
+++ b/filter/qa/pdf.cxx
@@ -372,6 +372,66 @@ CPPUNIT_TEST_FIXTURE(Test, testWatermarkRotateAngle)
     // i.e. the rotation angle was 270 for an A4 page, not the requested 45 
degrees.
     CPPUNIT_ASSERT_EQUAL(nExpectedRotateAngle, nActualRotateAngle);
 }
+
+#ifdef UNX
+CPPUNIT_TEST_FIXTURE(Test, testSignCertificatePEM)
+{
+    // Given an empty document:
+    std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+    if (!pPDFium)
+        return;
+
+    uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+        = xml::crypto::SEInitializer::create(m_xContext);
+    uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+        = xSEInitializer->createSecurityContext(OUString());
+    uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment
+        = xSecurityContext->getSecurityEnvironment();
+    OUString aKeyPath = createFileURL(u"key.pem");
+    SvFileStream aKeyStream(aKeyPath, StreamMode::READ);
+    OUString aKeyPem
+        = OUString::fromUtf8(read_uInt8s_ToOString(aKeyStream, 
aKeyStream.remainingSize()));
+    OUString aCertPath = createFileURL(u"cert.pem");
+    SvFileStream aCertStream(aCertPath, StreamMode::READ);
+    OUString aCertPem
+        = OUString::fromUtf8(read_uInt8s_ToOString(aCertStream, 
aCertStream.remainingSize()));
+    OUString aCaPath = createFileURL(u"ca.pem");
+    SvFileStream aCaStream(aCaPath, StreamMode::READ);
+    OUString aCaPem
+        = OUString::fromUtf8(read_uInt8s_ToOString(aCaStream, 
aCaStream.remainingSize()));
+    uno::Sequence<beans::PropertyValue> aFilterData{
+        comphelper::makePropertyValue("SignPDF", true),
+        comphelper::makePropertyValue("SignCertificateCertPem", aCertPem),
+        comphelper::makePropertyValue("SignCertificateKeyPem", aKeyPem),
+        comphelper::makePropertyValue("aSignCertificateCaPem", aCaPem),
+    };
+    mxComponent.set(loadFromDesktop("private:factory/swriter", 
"com.sun.star.text.TextDocument"));
+
+    // When exporting to PDF, and referring to a certificate using a 
cert/key/ca PEM, which is not
+    // in the NSS database:
+    uno::Reference<css::lang::XMultiServiceFactory> xFactory = 
getMultiServiceFactory();
+    uno::Reference<document::XFilter> xFilter(
+        xFactory->createInstance("com.sun.star.document.PDFFilter"), 
uno::UNO_QUERY);
+    uno::Reference<document::XExporter> xExporter(xFilter, uno::UNO_QUERY);
+    xExporter->setSourceDocument(mxComponent);
+    SvMemoryStream aStream;
+    uno::Reference<io::XOutputStream> xOutputStream(new 
utl::OStreamWrapper(aStream));
+    uno::Sequence<beans::PropertyValue> aDescriptor{
+        comphelper::makePropertyValue("FilterName", 
OUString("writer_pdf_Export")),
+        comphelper::makePropertyValue("FilterData", aFilterData),
+        comphelper::makePropertyValue("OutputStream", xOutputStream),
+    };
+    xFilter->filter(aDescriptor);
+
+    // Then make sure the resulting PDF has a signature:
+    std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+        = pPDFium->openDocument(aStream.GetData(), aStream.GetSize(), 
OString());
+    // Without the accompanying fix in place, this test would have failed, as 
signing was enabled
+    // without configured certificate, so the whole export failed.
+    CPPUNIT_ASSERT(pPdfDocument);
+    CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getSignatureCount());
+}
+#endif
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx
index 708891deab7d..e636f16e33ed 100644
--- a/filter/source/pdf/pdfexport.cxx
+++ b/filter/source/pdf/pdfexport.cxx
@@ -40,6 +40,7 @@
 #include <unotools/configmgr.hxx>
 #include <comphelper/compbase.hxx>
 #include <officecfg/Office/Common.hxx>
+#include <sfx2/lokhelper.hxx>
 
 #include "pdfexport.hxx"
 #include <strings.hrc>
@@ -526,6 +527,9 @@ bool PDFExport::Export( const OUString& rFile, const 
Sequence< PropertyValue >&
             aContext.DocumentInfo.Creator = aCreator;
 
             OUString aSignCertificateSubjectName;
+            OUString aSignCertificateCertPem;
+            OUString aSignCertificateKeyPem;
+            OUString aSignCertificateCaPem;
             for ( const beans::PropertyValue& rProp : rFilterData )
             {
                 if ( rProp.Name == "PageRange" )
@@ -689,6 +693,12 @@ bool PDFExport::Export( const OUString& rFile, const 
Sequence< PropertyValue >&
                     rProp.Value >>= aSignCertificate;
                 else if (rProp.Name == "SignCertificateSubjectName")
                     rProp.Value >>= aSignCertificateSubjectName;
+                else if (rProp.Name == "SignCertificateCertPem")
+                    rProp.Value >>= aSignCertificateCertPem;
+                else if (rProp.Name == "SignCertificateKeyPem")
+                    rProp.Value >>= aSignCertificateKeyPem;
+                else if (rProp.Name == "SignCertificateCaPem")
+                    rProp.Value >>= aSignCertificateCaPem;
                 else if ( rProp.Name == "SignatureTSA" )
                     rProp.Value >>= sSignTSA;
                 else if ( rProp.Name == "ExportPlaceholders" )
@@ -716,6 +726,24 @@ bool PDFExport::Export( const OUString& rFile, const 
Sequence< PropertyValue >&
                 aSignCertificate = 
GetCertificateFromSubjectName(aSignCertificateSubjectName);
             }
 
+            if (!aSignCertificate.is())
+            {
+                // Still no signing certificate configured, see if we got a 
ca/cert/key in PEM
+                // format:
+                if (!aSignCertificateCaPem.isEmpty())
+                {
+                    std::string aSignatureCa(aSignCertificateCaPem.toUtf8());
+                    std::vector<std::string> aCerts = 
SfxLokHelper::extractCertificates(aSignatureCa);
+                    SfxLokHelper::addCertificates(aCerts);
+                }
+                if (!aSignCertificateCertPem.isEmpty() && 
!aSignCertificateKeyPem.isEmpty())
+                {
+                    std::string 
aSignatureCert(aSignCertificateCertPem.toUtf8());
+                    std::string aSignatureKey(aSignCertificateKeyPem.toUtf8());
+                    aSignCertificate = 
SfxLokHelper::getSigningCertificate(aSignatureCert, aSignatureKey);
+                }
+            }
+
             aContext.URL        = 
aURL.GetMainURL(INetURLObject::DecodeMechanism::ToIUri);
 
             // set the correct version, depending on user request

Reply via email to