[Libreoffice-commits] core.git: Branch 'distro/cib/libreoffice-6-1' - 3 commits - include/vcl sc/source vcl/Library_vcl.mk vcl/qa vcl/source xmlsecurity/Library_xmlsecurity.mk xmlsecurity/qa xmlsecurity/source xmlsecurity/workben

Thorsten Behrens (via logerrit) logerrit at kemper.freedesktop.org
Sat Sep 12 09:26:16 UTC 2020


Rebased ref, commits from common ancestor:
commit f2b264077ea7e5e944de16580a30c2eecfadf50d
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Thu Sep 10 00:18:08 2020 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Sat Sep 12 11:24:44 2020 +0200

    Check range before accessing Calc sort userlist
    
    Change-Id: I74df0bc6db978e06e8014ac1bc0d76a66c7f4fe8

diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 07c4030382c2..487e7eec6626 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1520,9 +1520,9 @@ short ScTable::CompareCell(
                 bool bNaturalSort = aSortParam.bNaturalSort;    // natural sort
                 bool bCaseSens    = aSortParam.bCaseSens;       // case sensitivity
 
-                if (bUserDef)
+                ScUserList* pList = ScGlobal::GetUserList();
+                if (bUserDef && pList && pList->size() > aSortParam.nUserIndex)
                 {
-                    ScUserList* pList = ScGlobal::GetUserList();
                     const ScUserListData& rData = (*pList)[aSortParam.nUserIndex];
 
                     if ( bNaturalSort )
commit c258db7bea59bd536d71fd91c960d3bd9e1b4bb4
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Fri Sep 4 17:17:48 2020 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Sat Sep 12 11:24:41 2020 +0200

    xmlsecurity: pdf incremental updates that are non-commenting are invalid
    
    I.e. it's OK to add incremental updates for annotation/commenting
    purposes and that doesn't invalite existing signatures. Everything else
    does.
    
    (cherry picked from commit 61834cd574568613f0b0a2ee099a60fa5a8d9804)
    
    Conflicts:
            include/vcl/filter/PDFiumLibrary.hxx
            vcl/source/pdf/PDFiumLibrary.cxx
    
    Change-Id: I4607c242b3c6f6b01517b02407e9e7a095e2e069
    
    Conflicts:
            xmlsecurity/qa/unit/signing/signing.cxx

diff --git a/include/vcl/filter/PDFiumLibrary.hxx b/include/vcl/filter/PDFiumLibrary.hxx
index b9bceabb8acf..ffc70874c19b 100644
--- a/include/vcl/filter/PDFiumLibrary.hxx
+++ b/include/vcl/filter/PDFiumLibrary.hxx
@@ -17,11 +17,16 @@
 #include <memory>
 #include <rtl/instance.hxx>
 #include <vcl/dllapi.h>
+#include <vcl/checksum.hxx>
+
+#include <fpdf_doc.h>
 
 namespace vcl
 {
 namespace pdf
 {
+class PDFiumDocument;
+
 class VCL_DLLPUBLIC PDFium final
 {
 private:
@@ -33,6 +38,49 @@ public:
     ~PDFium();
 };
 
+class VCL_DLLPUBLIC PDFiumPage final
+{
+private:
+    FPDF_PAGE mpPage;
+
+private:
+    PDFiumPage(const PDFiumPage&) = delete;
+    PDFiumPage& operator=(const PDFiumPage&) = delete;
+
+public:
+    PDFiumPage(FPDF_PAGE pPage)
+        : mpPage(pPage)
+    {
+    }
+
+    ~PDFiumPage()
+    {
+        if (mpPage)
+            FPDF_ClosePage(mpPage);
+    }
+
+    /// Get bitmap checksum of the page, without annotations/commenting.
+    BitmapChecksum getChecksum();
+};
+
+class VCL_DLLPUBLIC PDFiumDocument final
+{
+private:
+    FPDF_DOCUMENT mpPdfDocument;
+
+private:
+    PDFiumDocument(const PDFiumDocument&) = delete;
+    PDFiumDocument& operator=(const PDFiumDocument&) = delete;
+
+public:
+    PDFiumDocument(FPDF_DOCUMENT pPdfDocument);
+    ~PDFiumDocument();
+
+    int getPageCount();
+
+    std::unique_ptr<PDFiumPage> openPage(int nIndex);
+};
+
 struct PDFiumLibrary : public rtl::StaticWithInit<std::shared_ptr<PDFium>, PDFiumLibrary>
 {
     std::shared_ptr<PDFium> operator()() { return std::make_shared<PDFium>(); }
diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx
index 5f487b15f48b..330c473ac6dc 100644
--- a/vcl/source/pdf/PDFiumLibrary.cxx
+++ b/vcl/source/pdf/PDFiumLibrary.cxx
@@ -15,6 +15,10 @@
 #include <vcl/filter/PDFiumLibrary.hxx>
 #include <fpdf_doc.h>
 
+#include <vcl/bitmap.hxx>
+
+#include <bitmapwriteaccess.hxx>
+
 namespace vcl
 {
 namespace pdf
@@ -31,6 +35,57 @@ PDFium::PDFium()
 
 PDFium::~PDFium() { FPDF_DestroyLibrary(); }
 
+PDFiumDocument::PDFiumDocument(FPDF_DOCUMENT pPdfDocument)
+    : mpPdfDocument(pPdfDocument)
+{
+}
+
+PDFiumDocument::~PDFiumDocument()
+{
+    if (mpPdfDocument)
+        FPDF_CloseDocument(mpPdfDocument);
+}
+
+std::unique_ptr<PDFiumPage> PDFiumDocument::openPage(int nIndex)
+{
+    std::unique_ptr<PDFiumPage> pPDFiumPage;
+    FPDF_PAGE pPage = FPDF_LoadPage(mpPdfDocument, nIndex);
+    if (pPage)
+    {
+        pPDFiumPage = std::make_unique<PDFiumPage>(pPage);
+    }
+    return pPDFiumPage;
+}
+
+int PDFiumDocument::getPageCount() { return FPDF_GetPageCount(mpPdfDocument); }
+
+BitmapChecksum PDFiumPage::getChecksum()
+{
+    size_t nPageWidth = FPDF_GetPageWidth(mpPage);
+    size_t nPageHeight = FPDF_GetPageHeight(mpPage);
+    FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1);
+    if (!pPdfBitmap)
+    {
+        return 0;
+    }
+
+    // Intentionally not using FPDF_ANNOT here, annotations/commenting is OK to not affect the
+    // checksum, signature verification wants this.
+    FPDF_RenderPageBitmap(pPdfBitmap, mpPage, /*start_x=*/0, /*start_y=*/0, nPageWidth, nPageHeight,
+                          /*rotate=*/0, /*flags=*/0);
+    Bitmap aBitmap(Size(nPageWidth, nPageHeight), 24);
+    {
+        BitmapScopedWriteAccess pWriteAccess(aBitmap);
+        const auto pPdfBuffer = static_cast<ConstScanline>(FPDFBitmap_GetBuffer(pPdfBitmap));
+        const int nStride = FPDFBitmap_GetStride(pPdfBitmap);
+        for (size_t nRow = 0; nRow < nPageHeight; ++nRow)
+        {
+            ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow);
+            pWriteAccess->CopyScanline(nRow, pPdfLine, ScanlineFormat::N32BitTcBgra, nStride);
+        }
+    }
+    return aBitmap.GetChecksum();
+}
 }
 } // end vcl::pdf
 
diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk
index a6f4e09d0c45..1389b87271c1 100644
--- a/xmlsecurity/Library_xmlsecurity.mk
+++ b/xmlsecurity/Library_xmlsecurity.mk
@@ -20,7 +20,10 @@ $(eval $(call gb_Library_add_defs,xmlsecurity,\
     -DXMLSECURITY_DLLIMPLEMENTATION \
 ))
 
-$(eval $(call gb_Library_use_externals,xmlsecurity,boost_headers))
+$(eval $(call gb_Library_use_externals,xmlsecurity,\
+	boost_headers \
+	$(if $(filter PDFIUM,$(BUILD_TYPE)),pdfium) \
+))
 
 $(eval $(call gb_Library_set_precompiled_header,xmlsecurity,$(SRCDIR)/xmlsecurity/inc/pch/precompiled_xmlsecurity))
 
diff --git a/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf b/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf
new file mode 100644
index 000000000000..f2b1a71096b2
Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf differ
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx
index 3876a19b566b..5d00a5506a61 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -95,6 +95,8 @@ public:
     void testPDFGood();
     /// Test a typical PDF where the signature is bad.
     void testPDFBad();
+    /// Test a maliciously manipulated signed pdf
+    void testPDFHideAndReplace();
     /// Test a typical PDF which is not signed.
     void testPDFNo();
 #endif
@@ -141,6 +143,7 @@ public:
 #if HAVE_FEATURE_PDFIMPORT
     CPPUNIT_TEST(testPDFGood);
     CPPUNIT_TEST(testPDFBad);
+    CPPUNIT_TEST(testPDFHideAndReplace);
     CPPUNIT_TEST(testPDFNo);
 #endif
     CPPUNIT_TEST(test96097Calc);
@@ -603,6 +606,22 @@ void SigningTest::testPDFBad()
     CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN), static_cast<int>(pObjectShell->GetDocumentSignatureState()));
 }
 
+void SigningTest::testPDFHideAndReplace()
+{
+    createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+              + "hide-and-replace-shadow-file-signed-2.pdf");
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT(pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT(pObjectShell);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 2 (BROKEN)
+    // - Actual  : 6 (NOTVALIDATED_PARTIAL_OK)
+    // i.e. a non-commenting update after a signature was not marked as invalid.
+    CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN),
+                         static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+}
+
 void SigningTest::testPDFNo()
 {
     createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "no.pdf");
diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx
index 7cf2c137c1c4..557180071a2c 100644
--- a/xmlsecurity/source/pdfio/pdfdocument.cxx
+++ b/xmlsecurity/source/pdfio/pdfdocument.cxx
@@ -12,6 +12,9 @@
 #include <memory>
 #include <vector>
 
+#include <config_features.h>
+
+#include <vcl/filter/PDFiumLibrary.hxx>
 #include <rtl/string.hxx>
 #include <rtl/ustrbuf.hxx>
 #include <sal/log.hxx>
@@ -20,6 +23,7 @@
 #include <svl/sigstruct.hxx>
 #include <svl/cryptosign.hxx>
 #include <vcl/filter/pdfdocument.hxx>
+#include <vcl/bitmap.hxx>
 
 using namespace com::sun::star;
 
@@ -133,6 +137,66 @@ bool IsCompleteSignature(SvStream& rStream, vcl::filter::PDFDocument& rDocument,
     size_t nFileEnd = rStream.Tell();
     return std::find(rAllEOFs.begin(), rAllEOFs.end(), nFileEnd) != rAllEOFs.end();
 }
+
+/// Collects the checksum of each page of one version of the PDF.
+void AnalyizeSignatureStream(SvMemoryStream& rStream, std::vector<BitmapChecksum>& rPageChecksums)
+{
+#if HAVE_FEATURE_PDFIUM
+    auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+    vcl::pdf::PDFiumDocument aPdfDocument(
+        FPDF_LoadMemDocument(rStream.GetData(), rStream.GetSize(), /*password=*/nullptr));
+
+    int nPageCount = aPdfDocument.getPageCount();
+    for (int nPage = 0; nPage < nPageCount; ++nPage)
+    {
+        std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage(aPdfDocument.openPage(nPage));
+        if (!pPdfPage)
+        {
+            return;
+        }
+
+        BitmapChecksum nPageChecksum = pPdfPage->getChecksum();
+        rPageChecksums.push_back(nPageChecksum);
+    }
+#else
+    (void)rStream;
+#endif
+}
+
+/**
+ * Checks if incremental updates after singing performed valid modifications only.
+ * Annotations/commenting is OK, other changes are not.
+ */
+bool IsValidSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignature)
+{
+    size_t nSignatureEOF = 0;
+    if (!GetEOFOfSignature(pSignature, nSignatureEOF))
+    {
+        return false;
+    }
+
+    SvMemoryStream aSignatureStream;
+    sal_uInt64 nPos = rStream.Tell();
+    rStream.Seek(0);
+    aSignatureStream.WriteStream(rStream, nSignatureEOF);
+    rStream.Seek(nPos);
+    aSignatureStream.Seek(0);
+    std::vector<BitmapChecksum> aSignedPages;
+    AnalyizeSignatureStream(aSignatureStream, aSignedPages);
+
+    SvMemoryStream aFullStream;
+    nPos = rStream.Tell();
+    rStream.Seek(0);
+    aFullStream.WriteStream(rStream);
+    rStream.Seek(nPos);
+    aFullStream.Seek(0);
+    std::vector<BitmapChecksum> aAllPages;
+    AnalyizeSignatureStream(aFullStream, aAllPages);
+
+    // Fail if any page looks different after signing and at the end. Annotations/commenting doesn't
+    // count, though.
+    return aSignedPages == aAllPages;
+}
 }
 
 namespace xmlsecurity
@@ -247,6 +311,11 @@ bool ValidateSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignat
         return false;
     }
     rInformation.bPartialDocumentSignature = !IsCompleteSignature(rStream, rDocument, pSignature);
+    if (!IsValidSignature(rStream, pSignature))
+    {
+        SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: invalid incremental update detected");
+        return false;
+    }
 
     // At this point there is no obviously missing info to validate the
     // signature.
diff --git a/xmlsecurity/workben/pdfverify.cxx b/xmlsecurity/workben/pdfverify.cxx
index 5763d8e6906d..01a21797d445 100644
--- a/xmlsecurity/workben/pdfverify.cxx
+++ b/xmlsecurity/workben/pdfverify.cxx
@@ -21,6 +21,7 @@
 #include <vcl/svapp.hxx>
 #include <vcl/graphicfilter.hxx>
 #include <vcl/filter/pdfdocument.hxx>
+#include <comphelper/scopeguard.hxx>
 
 #include <pdfio/pdfdocument.hxx>
 
@@ -78,11 +79,11 @@ int pdfVerify(int nArgc, char** pArgv)
                                                                     uno::UNO_QUERY);
     comphelper::setProcessServiceFactory(xMultiServiceFactory);
 
+    InitVCL();
+    comphelper::ScopeGuard g([] { DeInitVCL(); });
     if (nArgc > 3 && OString(pArgv[3]) == "-p")
     {
-        InitVCL();
         generatePreview(pArgv[1], pArgv[2]);
-        DeInitVCL();
         return 0;
     }
 
commit 12025e528ef50af9e3176a19465f860723e30871
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Sun May 31 11:50:20 2020 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Sat Sep 12 11:23:56 2020 +0200

    pdfium: only init pdfium library once and destroy on LO exit
    
    With more and more usage of PDFium, it is hard to keep track of
    the life-time of the PDFium library, so it can happen that a
    FPDF_DestroyLibrary happens when we still have another instance
    where PDFium is still use. The result of this is a crash. To
    prevent this, just initialize the library once and delete, when
    on LO exit.
    
    This can be improved in the future to only keep the library
    active when in actual use.
    
    [ Leaving out the vector graphic search bits, the motivation is to just
    have this in libreoffice-7-0, so that recent pdf sig verify improvements
    can be backported. ]
    
    (cherry picked from commit 067a8a954c8e1d8d6465a4ab5fb61e93f16c26c2)
    
    Conflicts:
            vcl/source/graphic/VectorGraphicSearch.cxx
    
    Change-Id: I5c7e5de7f8b97d10efb394c67c7a61b976c8d57c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102317
    Tested-by: Miklos Vajna <vmiklos at collabora.com>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    (cherry picked from commit b7de766b4dc5b4810277069bcf53a9f3737e87da)
    
    Conflicts:
            svx/source/svdraw/svdpdf.cxx
            svx/source/svdraw/svdpdf.hxx
            vcl/Library_vcl.mk
            vcl/qa/cppunit/pdfexport/pdfexport.cxx
            vcl/source/filter/ipdf/pdfread.cxx

diff --git a/include/vcl/filter/PDFiumLibrary.hxx b/include/vcl/filter/PDFiumLibrary.hxx
new file mode 100644
index 000000000000..b9bceabb8acf
--- /dev/null
+++ b/include/vcl/filter/PDFiumLibrary.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <config_features.h>
+
+#if HAVE_FEATURE_PDFIUM
+
+#include <memory>
+#include <rtl/instance.hxx>
+#include <vcl/dllapi.h>
+
+namespace vcl
+{
+namespace pdf
+{
+class VCL_DLLPUBLIC PDFium final
+{
+private:
+    PDFium(const PDFium&) = delete;
+    PDFium& operator=(const PDFium&) = delete;
+
+public:
+    PDFium();
+    ~PDFium();
+};
+
+struct PDFiumLibrary : public rtl::StaticWithInit<std::shared_ptr<PDFium>, PDFiumLibrary>
+{
+    std::shared_ptr<PDFium> operator()() { return std::make_shared<PDFium>(); }
+};
+}
+} // namespace vcl::pdf
+
+#endif // HAVE_FEATURE_PDFIUM
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 5f8bcd3af059..c306f5bfb8fb 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -299,6 +299,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/gdi/wall \
     vcl/source/gdi/scrptrun \
     vcl/source/gdi/CommonSalLayout \
+    vcl/source/pdf/PDFiumLibrary \
     vcl/source/graphic/GraphicLoader \
     vcl/source/graphic/GraphicObject \
     vcl/source/graphic/GraphicObject2 \
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index 5c4b4a8c7141..e1d7120e9db2 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -28,6 +28,8 @@
 #include <fpdf_text.h>
 #include <fpdfview.h>
 
+#include <vcl/filter/PDFiumLibrary.hxx>
+
 using namespace ::com::sun::star;
 
 static std::ostream& operator<<(std::ostream& rStrm, const Color& rColor)
@@ -53,6 +55,7 @@ class PdfExportTest : public test::BootstrapFixture, public unotest::MacrosTest
     SvMemoryStream maMemory;
     // Export the document as PDF, then parse it with PDFium.
     void exportAndParse(const OUString& rURL, const utl::MediaDescriptor& rDescriptor);
+    std::shared_ptr<vcl::pdf::PDFium> mpPDFium;
 
 public:
     PdfExportTest();
@@ -164,19 +167,13 @@ void PdfExportTest::setUp()
     mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
     mxDesktop.set(frame::Desktop::create(mxComponentContext));
 
-    FPDF_LIBRARY_CONFIG config;
-    config.version = 2;
-    config.m_pUserFontPaths = nullptr;
-    config.m_pIsolate = nullptr;
-    config.m_v8EmbedderSlot = 0;
-    FPDF_InitLibraryWithConfig(&config);
+    mpPDFium = vcl::pdf::PDFiumLibrary::get();
 }
 
 void PdfExportTest::tearDown()
 {
     FPDF_ClosePage(mpPdfPage);
     FPDF_CloseDocument(mpPdfDocument);
-    FPDF_DestroyLibrary();
 
     if (mxComponent.is())
         mxComponent->dispose();
diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx
index e3fe26332e2f..ec4d068ac007 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -20,6 +20,8 @@
 #include <vcl/graph.hxx>
 #include <bitmapwriteaccess.hxx>
 
+#include <vcl/filter/PDFiumLibrary.hxx>
+
 using namespace com::sun::star;
 
 namespace
@@ -58,12 +60,7 @@ double pointToPixel(double fPoint) { return fPoint / 72 * 96; }
 size_t generatePreview(SvStream& rStream, std::vector<Bitmap>& rBitmaps, sal_uInt64 nPos,
                        sal_uInt64 nSize, const size_t nFirstPage, int nPages)
 {
-    FPDF_LIBRARY_CONFIG aConfig;
-    aConfig.version = 2;
-    aConfig.m_pUserFontPaths = nullptr;
-    aConfig.m_pIsolate = nullptr;
-    aConfig.m_v8EmbedderSlot = 0;
-    FPDF_InitLibraryWithConfig(&aConfig);
+    auto pPdfium = vcl::pdf::PDFiumLibrary::get();
 
     // Read input into a buffer.
     SvMemoryStream aInBuffer;
@@ -119,7 +116,6 @@ size_t generatePreview(SvStream& rStream, std::vector<Bitmap>& rBitmaps, sal_uIn
     }
 
     FPDF_CloseDocument(pPdfDocument);
-    FPDF_DestroyLibrary();
 
     return rBitmaps.size();
 }
@@ -159,12 +155,7 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream, sal_uInt64 n
     else
     {
         // Downconvert to PDF-1.5.
-        FPDF_LIBRARY_CONFIG aConfig;
-        aConfig.version = 2;
-        aConfig.m_pUserFontPaths = nullptr;
-        aConfig.m_pIsolate = nullptr;
-        aConfig.m_v8EmbedderSlot = 0;
-        FPDF_InitLibraryWithConfig(&aConfig);
+        auto pPdfium = vcl::pdf::PDFiumLibrary::get();
 
         // Read input into a buffer.
         SvMemoryStream aInBuffer;
@@ -182,7 +173,6 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream, sal_uInt64 n
             return false;
 
         FPDF_CloseDocument(pPdfDocument);
-        FPDF_DestroyLibrary();
 
         aWriter.m_aStream.Seek(STREAM_SEEK_TO_BEGIN);
         rOutStream.WriteStream(aWriter.m_aStream);
diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx
new file mode 100644
index 000000000000..5f487b15f48b
--- /dev/null
+++ b/vcl/source/pdf/PDFiumLibrary.cxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <config_features.h>
+
+#if HAVE_FEATURE_PDFIUM
+
+#include <vcl/filter/PDFiumLibrary.hxx>
+#include <fpdf_doc.h>
+
+namespace vcl
+{
+namespace pdf
+{
+PDFium::PDFium()
+{
+    FPDF_LIBRARY_CONFIG aConfig;
+    aConfig.version = 2;
+    aConfig.m_pUserFontPaths = nullptr;
+    aConfig.m_pIsolate = nullptr;
+    aConfig.m_v8EmbedderSlot = 0;
+    FPDF_InitLibraryWithConfig(&aConfig);
+}
+
+PDFium::~PDFium() { FPDF_DestroyLibrary(); }
+
+}
+} // end vcl::pdf
+
+#endif // HAVE_FEATURE_PDFIUM
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list