include/vcl/pdfread.hxx                |   43 ++++++++++++++++-----------------
 vcl/inc/pdf/pdfcompat.hxx              |    9 ++++--
 vcl/source/filter/graphicfilter.cxx    |    3 +-
 vcl/source/filter/ipdf/pdfcompat.cxx   |   32 ++++++++++++++++--------
 vcl/source/filter/ipdf/pdfdocument.cxx |    4 ++-
 vcl/source/filter/ipdf/pdfread.cxx     |   24 +++++-------------
 6 files changed, 61 insertions(+), 54 deletions(-)

New commits:
commit 72efc1d55d546dee49f732432299810f6be5529c
Author:     Dr. David Alan Gilbert <d...@treblig.org>
AuthorDate: Sun May 25 16:17:02 2025 +0100
Commit:     David Gilbert <d...@treblig.org>
CommitDate: Fri Jun 13 22:05:47 2025 +0200

    tdf#162826: ipdf: Route bEncrypted up
    
    Route the bEncrypted flag up from createBinaryDataContainer into
    ImportPDF and to readPDF.  Flatten out importPdfVectorGraphicData as we go.
    
    (For some reason, clang-format is insisting on reformatting an unrelated
    block of text underneath my change; shrug)
    
    Change-Id: Ie964ace8a13232da27ef7b3a9c8b9d893a2abcc1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185758
    Tested-by: Jenkins
    Reviewed-by: David Gilbert <freedesk...@treblig.org>

diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx
index 8bd116b9f3b7..73bb0a8a05a4 100644
--- a/include/vcl/pdfread.hxx
+++ b/include/vcl/pdfread.hxx
@@ -29,28 +29,29 @@ VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, 
int nSize,
                                       std::vector<BitmapEx>& rBitmaps, size_t 
nFirstPage = 0,
                                       int nPages = 1, const basegfx::B2DTuple* 
pSizeHint = nullptr);
 
-/// Imports a PDF stream as a VectorGraphicData.
-VCL_DLLPUBLIC bool importPdfVectorGraphicData(
-    SvStream& rStream, std::shared_ptr<VectorGraphicData>& rVectorGraphicData,
-    sal_Int32 nPageIndex = -1,
-    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler = nullptr);
-
-/// Imports a PDF stream into rGraphic.
 VCL_DLLPUBLIC bool
-ImportPDF(SvStream& rStream, Graphic& rGraphic, sal_Int32 nPageIndex = -1,
-          const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler = nullptr);
-
-// When inserting a PDF file as an image or pasting PDF data from the 
clipboard, at least on a
-// Retina iMac, the resulting rendered image does not look sharp without this 
surprisingly large
-// extra scaling factor. Exact reasons unknown. And it isn't enough to have it 
be just 2 (which is
-// the actual Retina factor on my iMac). Possibly the fuzziness is related to 
what Pdfium uses to
-// render text.
-
-// Also, look at CountDPIScaleFactor() in vcl/source/window/window.cxx. The 
GetDPIScaleFactor() API
-// lies on macOS even more than it does on other platforms, it claims that the 
DPI scale factor is
-// always 1. But in fact most Macs nowadays have a HiDPI ("Retina") display. 
But we can't just "fix"
-// things by making GetDPIScaleFactor() always return 2 on macOS, even if that 
wouldn't be any more
-// wrong, because that then causes other regressions that I have no time to 
look into now.
+ImportPDF(SvStream& rStream, Graphic& rGraphic, sal_Int32 nPageIndex,
+          const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler,
+          bool& bEncrypted);
+
+inline bool ImportPDF(SvStream& rStream, Graphic& rGraphic)
+{
+    bool bEncrypted;
+
+    return ImportPDF(rStream, rGraphic, -1, nullptr, bEncrypted);
+}
+
+    // When inserting a PDF file as an image or pasting PDF data from the 
clipboard, at least on a
+    // Retina iMac, the resulting rendered image does not look sharp without 
this surprisingly large
+    // extra scaling factor. Exact reasons unknown. And it isn't enough to 
have it be just 2 (which is
+    // the actual Retina factor on my iMac). Possibly the fuzziness is related 
to what Pdfium uses to
+    // render text.
+
+    // Also, look at CountDPIScaleFactor() in vcl/source/window/window.cxx. 
The GetDPIScaleFactor() API
+    // lies on macOS even more than it does on other platforms, it claims that 
the DPI scale factor is
+    // always 1. But in fact most Macs nowadays have a HiDPI ("Retina") 
display. But we can't just "fix"
+    // things by making GetDPIScaleFactor() always return 2 on macOS, even if 
that wouldn't be any more
+    // wrong, because that then causes other regressions that I have no time 
to look into now.
 
 #ifdef MACOSX
 constexpr int PDF_INSERT_MAGIC_SCALE_FACTOR = 8;
diff --git a/vcl/inc/pdf/pdfcompat.hxx b/vcl/inc/pdf/pdfcompat.hxx
index 395d8ba6d8ba..4cce2a12b0df 100644
--- a/vcl/inc/pdf/pdfcompat.hxx
+++ b/vcl/inc/pdf/pdfcompat.hxx
@@ -42,7 +42,7 @@ bool getCompatibleStream(
     bool& bEncrypted);
 
 BinaryDataContainer createBinaryDataContainer(
-    SvStream& rStream,
+    SvStream& rStream, bool& bEncrypted,
     const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler = nullptr);
 
 } // end of vcl::filter::ipdf namespace
diff --git a/vcl/source/filter/graphicfilter.cxx 
b/vcl/source/filter/graphicfilter.cxx
index 2f2ca2fb1be7..9e8e604354c7 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -1139,7 +1139,8 @@ ErrCode GraphicFilter::readPDF(
    SvStream& rStream, Graphic& rGraphic, GfxLinkType& rLinkType, sal_Int32 
nPageIndex,
    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler)
 {
-    if (vcl::ImportPDF(rStream, rGraphic, nPageIndex, xInteractionHandler))
+    bool bEncrypted;
+    if (vcl::ImportPDF(rStream, rGraphic, nPageIndex, xInteractionHandler, 
bEncrypted))
     {
         rLinkType = GfxLinkType::NativePdf;
         return ERRCODE_NONE;
diff --git a/vcl/source/filter/ipdf/pdfcompat.cxx 
b/vcl/source/filter/ipdf/pdfcompat.cxx
index ed224d844c2a..57e53fdb76d0 100644
--- a/vcl/source/filter/ipdf/pdfcompat.cxx
+++ b/vcl/source/filter/ipdf/pdfcompat.cxx
@@ -136,10 +136,9 @@ bool getCompatibleStream(
 }
 
 BinaryDataContainer createBinaryDataContainer(
-    SvStream& rStream,
+    SvStream& rStream, bool& bEncrypted,
     const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler)
 {
-    bool bEncrypted;
     // Save the original PDF stream for later use.
     SvMemoryStream aMemoryStream;
     if (!getCompatibleStream(rStream, aMemoryStream, xInteractionHandler, 
bEncrypted))
diff --git a/vcl/source/filter/ipdf/pdfread.cxx 
b/vcl/source/filter/ipdf/pdfread.cxx
index 574c53e959b7..74df41923217 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -101,30 +101,19 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, 
std::vector<BitmapEx>& r
     return rBitmaps.size();
 }
 
-bool importPdfVectorGraphicData(
-    SvStream& rStream, std::shared_ptr<VectorGraphicData>& rVectorGraphicData, 
sal_Int32 nPageIndex,
-    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler)
+bool ImportPDF(SvStream& rStream, Graphic& rGraphic, sal_Int32 nPageIndex,
+               const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler,
+               bool& bEncrypted)
 {
     BinaryDataContainer aDataContainer
-        = vcl::pdf::createBinaryDataContainer(rStream, xInteractionHandler);
+        = vcl::pdf::createBinaryDataContainer(rStream, bEncrypted, 
xInteractionHandler);
     if (aDataContainer.isEmpty())
     {
         SAL_WARN("vcl.filter", "ImportPDF: empty PDF data array");
         return false;
     }
-
-    rVectorGraphicData = std::make_shared<VectorGraphicData>(
+    std::shared_ptr<VectorGraphicData> pVectorGraphicData = 
std::make_shared<VectorGraphicData>(
         aDataContainer, VectorGraphicDataType::Pdf, nPageIndex);
-
-    return true;
-}
-
-bool ImportPDF(SvStream& rStream, Graphic& rGraphic, sal_Int32 nPageIndex,
-               const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler)
-{
-    std::shared_ptr<VectorGraphicData> pVectorGraphicData;
-    if (!importPdfVectorGraphicData(rStream, pVectorGraphicData, nPageIndex, 
xInteractionHandler))
-        return false;
     rGraphic = Graphic(pVectorGraphicData);
     return true;
 }
@@ -354,9 +343,10 @@ size_t ImportPDFUnloaded(const OUString& rURL, 
std::vector<PDFGraphicResult>& rG
 {
     std::unique_ptr<SvStream> xStream(
         ::utl::UcbStreamHelper::CreateStream(rURL, StreamMode::READ | 
StreamMode::SHARE_DENYNONE));
+    bool bEncrypted;
 
     // Save the original PDF stream for later use.
-    BinaryDataContainer aDataContainer = 
vcl::pdf::createBinaryDataContainer(*xStream);
+    BinaryDataContainer aDataContainer = 
vcl::pdf::createBinaryDataContainer(*xStream, bEncrypted);
     if (aDataContainer.isEmpty())
         return 0;
 
commit bb8fccd3655dca712d6dd414cc274861bd7b0462
Author:     Dr. David Alan Gilbert <d...@treblig.org>
AuthorDate: Sun May 25 14:30:37 2025 +0100
Commit:     David Gilbert <d...@treblig.org>
CommitDate: Fri Jun 13 22:05:36 2025 +0200

    tdf#162826: ipdf: Convert for encrypted, correctly versioned, files
    
    convertToHighestSupported downconverts PDFs to a magical 1.6 version
    due to some historic bug; it's also used in a corner of the ipdf
    vector convert to force a conversion on a buggy input file.
    
    Use it to also force a conversion in the encrypted case even if the
    input was of the expected version.
    Pass up a flag to indicate if the file was encrypted.
    
    Change-Id: I3a8d17851349157ec5b8e7d9a2548c1a21a198a7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185757
    Reviewed-by: David Gilbert <freedesk...@treblig.org>
    Tested-by: Jenkins

diff --git a/vcl/inc/pdf/pdfcompat.hxx b/vcl/inc/pdf/pdfcompat.hxx
index 35634f6982a9..395d8ba6d8ba 100644
--- a/vcl/inc/pdf/pdfcompat.hxx
+++ b/vcl/inc/pdf/pdfcompat.hxx
@@ -28,15 +28,18 @@ bool isCompatible(SvStream& rInStream);
 /// Converts to highest supported format version (currently 1.6).
 /// Usually used to deal with missing referenced objects in the
 /// source pdf stream.
+/// The conversion takes place if either the stream is encrypted, or 'bForce' 
is true
 bool convertToHighestSupported(
     SvStream& rInStream, SvStream& rOutStream,
-    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler = nullptr);
+    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler, bool bForce,
+    bool& bEncrypted);
 
 /// Takes care of transparently downgrading the version of the PDF stream in
 /// case it's too new for our PDF export.
 bool getCompatibleStream(
     SvStream& rInStream, SvStream& rOutStream,
-    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler);
+    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler,
+    bool& bEncrypted);
 
 BinaryDataContainer createBinaryDataContainer(
     SvStream& rStream,
diff --git a/vcl/source/filter/ipdf/pdfcompat.cxx 
b/vcl/source/filter/ipdf/pdfcompat.cxx
index 50a9010a4917..ed224d844c2a 100644
--- a/vcl/source/filter/ipdf/pdfcompat.cxx
+++ b/vcl/source/filter/ipdf/pdfcompat.cxx
@@ -39,14 +39,16 @@ bool isCompatible(SvStream& rInStream)
 /// Converts to highest supported format version (1.6).
 /// Usually used to deal with missing referenced objects in source
 /// pdf stream.
-
+/// The conversion takes place if either the stream is encrypted, or 'bForce' 
is true
 bool convertToHighestSupported(
     SvStream& rInStream, SvStream& rOutStream,
-    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler)
+    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler, bool bForce,
+    bool& bEncrypted)
 {
     sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN;
     sal_uInt64 nSize = STREAM_SEEK_TO_END;
     rInStream.Seek(nPos);
+    bEncrypted = false;
     // Convert to PDF-1.6.
     auto pPdfium = vcl::pdf::PDFiumLibrary::get();
     if (!pPdfium)
@@ -83,6 +85,7 @@ bool convertToHighestSupported(
             }
 
             // We don't have a filename for the GUI here
+            bEncrypted = true;
             bAgain = vcl::pdf::getPassword(xInteractionHandler, aPassword, 
!bAgain, u"PDF"_ustr);
             SAL_INFO("vcl.filter", "convertToHighestSupported pass result: " 
<< bAgain);
             if (!bAgain)
@@ -102,9 +105,14 @@ bool convertToHighestSupported(
     } while (bAgain);
 
     aSaved.Seek(STREAM_SEEK_TO_BEGIN);
-    SAL_INFO("vcl.filter", "convertToHighestSupported do write");
-    rOutStream.WriteStream(aSaved);
+    if (bEncrypted || bForce)
+    {
+        SAL_INFO("vcl.filter", "convertToHighestSupported do write");
+        rOutStream.WriteStream(aSaved);
+    }
 
+    SAL_INFO("vcl.filter",
+             "convertToHighestSupported exit: encrypted: " << bEncrypted << " 
force: " << bForce);
     return rOutStream.good();
 }
 
@@ -112,15 +120,17 @@ bool convertToHighestSupported(
 /// case it's too new for our PDF export.
 bool getCompatibleStream(
     SvStream& rInStream, SvStream& rOutStream,
-    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler)
+    const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler,
+    bool& bEncrypted)
 {
     bool bCompatible = isCompatible(rInStream);
+
+    // This will convert if either the file is encrypted, or !bCompatible
+    convertToHighestSupported(rInStream, rOutStream, xInteractionHandler, 
!bCompatible, bEncrypted);
     rInStream.Seek(STREAM_SEEK_TO_BEGIN);
-    if (bCompatible)
-        // Not converting.
+    if (bCompatible && !bEncrypted)
+        // Just pass the original through
         rOutStream.WriteStream(rInStream, STREAM_SEEK_TO_END);
-    else
-        convertToHighestSupported(rInStream, rOutStream, xInteractionHandler);
 
     return rOutStream.good();
 }
@@ -129,9 +139,10 @@ BinaryDataContainer createBinaryDataContainer(
     SvStream& rStream,
     const css::uno::Reference<css::task::XInteractionHandler>& 
xInteractionHandler)
 {
+    bool bEncrypted;
     // Save the original PDF stream for later use.
     SvMemoryStream aMemoryStream;
-    if (!getCompatibleStream(rStream, aMemoryStream, xInteractionHandler))
+    if (!getCompatibleStream(rStream, aMemoryStream, xInteractionHandler, 
bEncrypted))
         return {};
 
     const sal_uInt64 nStreamLength = aMemoryStream.TellEnd();
diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx 
b/vcl/source/filter/ipdf/pdfdocument.cxx
index 0b7c01a56ac1..270248f533d9 100644
--- a/vcl/source/filter/ipdf/pdfdocument.cxx
+++ b/vcl/source/filter/ipdf/pdfdocument.cxx
@@ -1384,7 +1384,9 @@ bool PDFDocument::ReadWithPossibleFixup(SvStream& rStream)
     // Read failed, try a roundtrip through pdfium and then retry.
     rStream.Seek(0);
     SvMemoryStream aStandardizedStream;
-    vcl::pdf::convertToHighestSupported(rStream, aStandardizedStream);
+    bool bEncrypted;
+    vcl::pdf::convertToHighestSupported(rStream, aStandardizedStream, nullptr, 
true /* force */,
+                                        bEncrypted);
     return Read(aStandardizedStream);
 }
 

Reply via email to