diff options
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/pdf/pdfwriter_impl.hxx | 4 | ||||
-rw-r--r-- | vcl/qa/cppunit/PDFiumLibraryTest.cxx | 18 | ||||
-rw-r--r-- | vcl/qa/cppunit/filter/ipdf/ipdf.cxx | 2 | ||||
-rw-r--r-- | vcl/qa/cppunit/pdfexport/data/rectangles.pdf | 54 | ||||
-rw-r--r-- | vcl/qa/cppunit/pdfexport/pdfexport.cxx | 50 | ||||
-rw-r--r-- | vcl/source/filter/ipdf/pdfread.cxx | 8 | ||||
-rw-r--r-- | vcl/source/gdi/pdfobjectcopier.cxx | 29 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 32 | ||||
-rw-r--r-- | vcl/source/graphic/VectorGraphicSearch.cxx | 3 | ||||
-rw-r--r-- | vcl/source/pdf/PDFiumLibrary.cxx | 13 |
10 files changed, 186 insertions, 27 deletions
diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx index 228df387fb6d..d718529476b9 100644 --- a/vcl/inc/pdf/pdfwriter_impl.hxx +++ b/vcl/inc/pdf/pdfwriter_impl.hxx @@ -807,9 +807,9 @@ i12626 void addRoleMap(OString aAlias, PDFWriter::StructElement eType); /* this function implements part of the PDF spec algorithm 3.1 in encryption, the rest (the actual encryption) is in PDFWriterImpl::writeBuffer */ - void checkAndEnableStreamEncryption( sal_Int32 nObject ); + void checkAndEnableStreamEncryption( sal_Int32 nObject ) override; - void disableStreamEncryption() { m_bEncryptThisStream = false; }; + void disableStreamEncryption() override { m_bEncryptThisStream = false; }; /* */ void enableStringEncryption( sal_Int32 nObject ); diff --git a/vcl/qa/cppunit/PDFiumLibraryTest.cxx b/vcl/qa/cppunit/PDFiumLibraryTest.cxx index 9ba40c438f50..1f82f24acccf 100644 --- a/vcl/qa/cppunit/PDFiumLibraryTest.cxx +++ b/vcl/qa/cppunit/PDFiumLibraryTest.cxx @@ -70,7 +70,8 @@ void PDFiumLibraryTest::testDocument() auto pPdfium = vcl::pdf::PDFiumLibrary::get(); CPPUNIT_ASSERT(pPdfium); - auto pDocument = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize()); + auto pDocument + = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString()); CPPUNIT_ASSERT(pDocument); CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount()); @@ -95,7 +96,8 @@ void PDFiumLibraryTest::testPages() auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer(); auto pPdfium = vcl::pdf::PDFiumLibrary::get(); - auto pDocument = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize()); + auto pDocument + = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString()); CPPUNIT_ASSERT(pDocument); CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount()); @@ -119,7 +121,8 @@ void PDFiumLibraryTest::testPageObjects() auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer(); auto pPdfium = vcl::pdf::PDFiumLibrary::get(); - auto pDocument = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize()); + auto pDocument + = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString()); CPPUNIT_ASSERT(pDocument); CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount()); @@ -171,7 +174,8 @@ void PDFiumLibraryTest::testAnnotationsMadeInEvince() auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer(); auto pPdfium = vcl::pdf::PDFiumLibrary::get(); - auto pDocument = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize()); + auto pDocument + = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString()); CPPUNIT_ASSERT(pDocument); CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount()); @@ -226,7 +230,8 @@ void PDFiumLibraryTest::testAnnotationsMadeInAcrobat() auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer(); auto pPdfium = vcl::pdf::PDFiumLibrary::get(); - auto pDocument = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize()); + auto pDocument + = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString()); CPPUNIT_ASSERT(pDocument); CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount()); @@ -337,7 +342,8 @@ void PDFiumLibraryTest::testAnnotationsDifferentTypes() auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer(); auto pPdfium = vcl::pdf::PDFiumLibrary::get(); - auto pDocument = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize()); + auto pDocument + = pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString()); CPPUNIT_ASSERT(pDocument); CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount()); diff --git a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx index ca5460e63b48..b57ead0f6702 100644 --- a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx +++ b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx @@ -134,7 +134,7 @@ CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testPDFAddVisibleSignatureLastPage) aMemory.WriteStream(aFile); // Last page. std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument - = pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize()); + = pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), OString()); std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/1); // Without the accompanying fix in place, this test would have failed with: // - Expected: 1 diff --git a/vcl/qa/cppunit/pdfexport/data/rectangles.pdf b/vcl/qa/cppunit/pdfexport/data/rectangles.pdf new file mode 100644 index 000000000000..6911d229aa06 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/rectangles.pdf @@ -0,0 +1,54 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [0 0 200 300] + /Count 1 + /Kids [3 0 R] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R +>> +endobj +4 0 obj << + /Length 188 +>> +stream +q +0 0 0 rg +0 290 10 10 re B* +10 150 50 30 re B* +0 0 1 rg +190 290 10 10 re B* +70 232 50 30 re B* +0 1 0 rg +190 0 10 10 re B* +130 150 50 30 re B* +1 0 0 rg +0 0 10 10 re B* +70 67 50 30 re B* +Q +endstream +endobj +xref +0 5 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000157 00000 n +0000000226 00000 n +trailer << + /Root 1 0 R + /Size 5 +>> +startxref +466 +%%EOF diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx index 2531dab1a3f4..d77cc4a4b00d 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -68,7 +68,7 @@ protected: utl::TempFile maTempFile; SvMemoryStream maMemory; utl::MediaDescriptor aMediaDescriptor; - std::unique_ptr<vcl::pdf::PDFiumDocument> parseExport(); + std::unique_ptr<vcl::pdf::PDFiumDocument> parseExport(const OString& rPassword = OString()); std::shared_ptr<vcl::pdf::PDFium> mpPDFium; public: @@ -81,13 +81,13 @@ public: PdfExportTest::PdfExportTest() { maTempFile.EnableKillingFile(); } -std::unique_ptr<vcl::pdf::PDFiumDocument> PdfExportTest::parseExport() +std::unique_ptr<vcl::pdf::PDFiumDocument> PdfExportTest::parseExport(const OString& rPassword) { SvFileStream aFile(maTempFile.GetURL(), StreamMode::READ); maMemory.WriteStream(aFile); std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument - = pPDFium->openDocument(maMemory.GetData(), maMemory.GetSize()); + = pPDFium->openDocument(maMemory.GetData(), maMemory.GetSize(), rPassword); CPPUNIT_ASSERT(pPdfDocument); return pPdfDocument; } @@ -3407,6 +3407,50 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageAnnots) // i.e. not only the hyperlink but also the 2 comments were exported, leading to duplication. CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount()); } + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageEncryption) +{ + // Given an empty document, with an inserted PDF image: + mxComponent = loadFromDesktop("private:factory/swriter"); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xGraphicObject( + xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY); + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "rectangles.pdf"; + xGraphicObject->setPropertyValue("GraphicURL", uno::Any(aURL)); + uno::Reference<drawing::XShape> xShape(xGraphicObject, uno::UNO_QUERY); + xShape->setSize(awt::Size(1000, 1000)); + uno::Reference<text::XTextContent> xTextContent(xGraphicObject, uno::UNO_QUERY); + xText->insertTextContent(xCursor->getStart(), xTextContent, /*bAbsorb=*/false); + + // When saving as encrypted PDF: + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + uno::Sequence<beans::PropertyValue> aFilterData = { + comphelper::makePropertyValue("EncryptFile", true), + comphelper::makePropertyValue("DocumentOpenPassword", OUString("secret")), + }; + aMediaDescriptor["FilterData"] <<= aFilterData; + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Then make sure that the image is not lost: + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport("secret"); + CPPUNIT_ASSERT(pPdfDocument); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount()); + std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pPageObject->getType()); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 0 + // i.e. instead of the white background and the actual form child, the image was lost due to + // missing encryption. + CPPUNIT_ASSERT_EQUAL(2, pPageObject->getFormObjectCount()); +} } // end anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 112aa411a67d..8510b0a0c207 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -79,7 +79,7 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream) { // Load the buffer using pdfium. std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument - = pPdfium->openDocument(aInBuffer.GetData(), aInBuffer.GetSize()); + = pPdfium->openDocument(aInBuffer.GetData(), aInBuffer.GetSize(), OString()); if (!pPdfDocument) return false; @@ -128,7 +128,8 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<BitmapEx>& r } // Load the buffer using pdfium. - std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = pPdfium->openDocument(pBuffer, nSize); + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument + = pPdfium->openDocument(pBuffer, nSize, OString()); if (!pPdfDocument) return 0; @@ -441,7 +442,8 @@ size_t ImportPDFUnloaded(const OUString& rURL, std::vector<PDFGraphicResult>& rG } // Load the buffer using pdfium. - auto pPdfDocument = pPdfium->openDocument(pGfxLink->GetData(), pGfxLink->GetDataSize()); + auto pPdfDocument + = pPdfium->openDocument(pGfxLink->GetData(), pGfxLink->GetDataSize(), OString()); if (!pPdfDocument) return 0; diff --git a/vcl/source/gdi/pdfobjectcopier.cxx b/vcl/source/gdi/pdfobjectcopier.cxx index 1cb6c209d699..93b7b4989710 100644 --- a/vcl/source/gdi/pdfobjectcopier.cxx +++ b/vcl/source/gdi/pdfobjectcopier.cxx @@ -113,12 +113,10 @@ sal_Int32 PDFObjectCopier::copyExternalResource(SvMemoryStream& rDocBuffer, aLine.append(" >>\n"); } - if (filter::PDFStreamElement* pStream = rObject.GetStream()) + filter::PDFStreamElement* pStream = rObject.GetStream(); + if (pStream) { aLine.append("stream\n"); - SvMemoryStream& rStream = pStream->GetMemory(); - aLine.append(static_cast<const char*>(rStream.GetData()), rStream.GetSize()); - aLine.append("\nendstream\n"); } if (filter::PDFArrayElement* pArray = rObject.GetArray()) @@ -146,13 +144,32 @@ sal_Int32 PDFObjectCopier::copyExternalResource(SvMemoryStream& rDocBuffer, aLine.append("\n"); } - aLine.append("endobj\n\n"); - // We have the whole object, now write it to the output. if (!m_rContainer.updateObject(nObject)) return -1; if (!m_rContainer.writeBuffer(aLine.getStr(), aLine.getLength())) return -1; + aLine.setLength(0); + + if (pStream) + { + SvMemoryStream& rStream = pStream->GetMemory(); + m_rContainer.checkAndEnableStreamEncryption(nObject); + aLine.append(static_cast<const char*>(rStream.GetData()), rStream.GetSize()); + if (!m_rContainer.writeBuffer(aLine.getStr(), aLine.getLength())) + return -1; + aLine.setLength(0); + m_rContainer.disableStreamEncryption(); + + aLine.append("\nendstream\n"); + if (!m_rContainer.writeBuffer(aLine.getStr(), aLine.getLength())) + return -1; + aLine.setLength(0); + } + + aLine.append("endobj\n\n"); + if (!m_rContainer.writeBuffer(aLine.getStr(), aLine.getLength())) + return -1; return nObject; } diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index ae78eda251e5..f16bdc090f03 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -8659,16 +8659,34 @@ void PDFWriterImpl::writeReferenceXObject(const ReferenceXObjectEmit& rEmit) aLine.append(nLength); aLine.append(">>\nstream\n"); + if (g_bDebugDisableCompression) + { + emitComment("PDFWriterImpl::writeReferenceXObject, WrappedFormObject"); + } + if (!updateObject(nWrappedFormObject)) + return; + if (!writeBuffer(aLine.getStr(), aLine.getLength())) + return; + aLine.setLength(0); + + checkAndEnableStreamEncryption(nWrappedFormObject); // Copy the original page streams to the form XObject stream. aLine.append(static_cast<const char*>(aStream.GetData()), aStream.GetSize()); - aLine.append("\nendstream\nendobj\n\n"); - if (!updateObject(nWrappedFormObject)) + if (!writeBuffer(aLine.getStr(), aLine.getLength())) return; + aLine.setLength(0); + disableStreamEncryption(); + + aLine.append("\nendstream\nendobj\n\n"); if (!writeBuffer(aLine.getStr(), aLine.getLength())) return; } OStringBuffer aLine; + if (g_bDebugDisableCompression) + { + emitComment("PDFWriterImpl::writeReferenceXObject, FormObject"); + } if (!updateObject(rEmit.m_nFormObject)) return; @@ -8747,7 +8765,17 @@ void PDFWriterImpl::writeReferenceXObject(const ReferenceXObjectEmit& rEmit) aLine.append(aStream.getLength()); aLine.append(">>\nstream\n"); + if (!writeBuffer(aLine.getStr(), aLine.getLength())) + return; + aLine.setLength(0); + + checkAndEnableStreamEncryption(rEmit.m_nFormObject); aLine.append(aStream.getStr()); + if (!writeBuffer(aLine.getStr(), aLine.getLength())) + return; + aLine.setLength(0); + disableStreamEncryption(); + aLine.append("\nendstream\nendobj\n\n"); CHECK_RETURN2(writeBuffer(aLine.getStr(), aLine.getLength())); } diff --git a/vcl/source/graphic/VectorGraphicSearch.cxx b/vcl/source/graphic/VectorGraphicSearch.cxx index 710c6e5f52e6..63dae6e5277d 100644 --- a/vcl/source/graphic/VectorGraphicSearch.cxx +++ b/vcl/source/graphic/VectorGraphicSearch.cxx @@ -231,7 +231,8 @@ bool VectorGraphicSearch::searchPDF(std::shared_ptr<VectorGraphicData> const& rD } mpImplementation->mpPdfDocument = mpImplementation->mpPDFium->openDocument( - rData->getBinaryDataContainer().getData(), rData->getBinaryDataContainer().getSize()); + rData->getBinaryDataContainer().getData(), rData->getBinaryDataContainer().getSize(), + OString()); if (!mpImplementation->mpPdfDocument) { diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx index d02e2a0bab49..b02358d43a9c 100644 --- a/vcl/source/pdf/PDFiumLibrary.cxx +++ b/vcl/source/pdf/PDFiumLibrary.cxx @@ -425,7 +425,8 @@ public: const OUString& getLastError() const override { return maLastError; } - std::unique_ptr<PDFiumDocument> openDocument(const void* pData, int nSize) override; + std::unique_ptr<PDFiumDocument> openDocument(const void* pData, int nSize, + const OString& rPassword) override; PDFErrorType getLastErrorCode() override; std::unique_ptr<PDFiumBitmap> createBitmap(int nWidth, int nHeight, int nAlpha) override; }; @@ -443,12 +444,18 @@ PDFiumImpl::PDFiumImpl() PDFiumImpl::~PDFiumImpl() { FPDF_DestroyLibrary(); } -std::unique_ptr<PDFiumDocument> PDFiumImpl::openDocument(const void* pData, int nSize) +std::unique_ptr<PDFiumDocument> PDFiumImpl::openDocument(const void* pData, int nSize, + const OString& rPassword) { maLastError = OUString(); std::unique_ptr<PDFiumDocument> pPDFiumDocument; - FPDF_DOCUMENT pDocument = FPDF_LoadMemDocument(pData, nSize, /*password=*/nullptr); + FPDF_BYTESTRING pPassword = nullptr; + if (!rPassword.isEmpty()) + { + pPassword = rPassword.getStr(); + } + FPDF_DOCUMENT pDocument = FPDF_LoadMemDocument(pData, nSize, pPassword); if (!pDocument) { |