summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xmlsecurity/pdfio/pdfdocument.hxx33
-rw-r--r--vcl/qa/cppunit/pdfexport/data/tdf105093.odpbin0 -> 211126 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/pdfexport.cxx50
-rw-r--r--xmlsecurity/source/pdfio/pdfdocument.cxx36
4 files changed, 88 insertions, 31 deletions
diff --git a/include/xmlsecurity/pdfio/pdfdocument.hxx b/include/xmlsecurity/pdfio/pdfdocument.hxx
index 5a8ea6c2c71d..5f64b650ed17 100644
--- a/include/xmlsecurity/pdfio/pdfdocument.hxx
+++ b/include/xmlsecurity/pdfio/pdfdocument.hxx
@@ -90,6 +90,37 @@ public:
void SetStreamBuffer(std::unique_ptr<SvMemoryStream>& pStreamBuffer);
};
+/// Array object: a list.
+class XMLSECURITY_DLLPUBLIC PDFArrayElement : public PDFElement
+{
+ /// Location after the '[' token.
+ sal_uInt64 m_nOffset = 0;
+ std::vector<PDFElement*> m_aElements;
+public:
+ PDFArrayElement();
+ bool Read(SvStream& rStream) override;
+ void PushBack(PDFElement* pElement);
+ const std::vector<PDFElement*>& GetElements();
+};
+
+/// Reference object: something with a unique ID.
+class XMLSECURITY_DLLPUBLIC PDFReferenceElement : public PDFElement
+{
+ PDFDocument& m_rDoc;
+ int m_fObjectValue;
+ int m_fGenerationValue;
+
+public:
+ PDFReferenceElement(PDFDocument& rDoc, int fObjectValue, int fGenerationValue);
+ bool Read(SvStream& rStream) override;
+ /// Assuming the reference points to a number object, return its value.
+ double LookupNumber(SvStream& rStream) const;
+ /// Lookup referenced object, without assuming anything about its contents.
+ PDFObjectElement* LookupObject();
+ int GetObjectValue() const;
+ int GetGenerationValue() const;
+};
+
/// Stream object: a byte array with a known length.
class XMLSECURITY_DLLPUBLIC PDFStreamElement : public PDFElement
{
@@ -146,6 +177,8 @@ public:
const std::map<OString, PDFElement*>& GetItems() const;
/// Looks up an object which is only referenced in this dictionary.
PDFObjectElement* LookupObject(const OString& rDictionaryKey);
+ /// Looks up an element which is contained in this dictionary.
+ PDFElement* LookupElement(const OString& rDictionaryKey);
};
enum class TokenizeMode
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf105093.odp b/vcl/qa/cppunit/pdfexport/data/tdf105093.odp
new file mode 100644
index 000000000000..82ce29cda0c1
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf105093.odp
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index 1c665b8d2174..af6e86b7d17e 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -42,12 +42,15 @@ public:
void testTdf106059();
/// Tests that text highlight from Impress is not lost.
void testTdf105461();
+ /// Tests that embedded video from Impress is not exported as a linked one.
+ void testTdf105093();
#endif
CPPUNIT_TEST_SUITE(PdfExportTest);
#if HAVE_FEATURE_PDFIUM
CPPUNIT_TEST(testTdf106059);
CPPUNIT_TEST(testTdf105461);
+ CPPUNIT_TEST(testTdf105093);
#endif
CPPUNIT_TEST_SUITE_END();
};
@@ -150,6 +153,53 @@ void PdfExportTest::testTdf105461()
// This failed, stream contained no filled rectangle.
CPPUNIT_ASSERT(it != pEnd);
}
+
+void PdfExportTest::testTdf105093()
+{
+ // Import the bugdoc and export as PDF.
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf105093.odp";
+ mxComponent = loadFromDesktop(aURL);
+ CPPUNIT_ASSERT(mxComponent.is());
+
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export");
+ xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Parse the export result.
+ xmlsecurity::pdfio::PDFDocument aDocument;
+ SvFileStream aStream(aTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ // The document has one page.
+ std::vector<xmlsecurity::pdfio::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ // Get page annotations.
+ auto pAnnots = dynamic_cast<xmlsecurity::pdfio::PDFArrayElement*>(aPages[0]->Lookup("Annots"));
+ CPPUNIT_ASSERT(pAnnots);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pAnnots->GetElements().size());
+ auto pAnnotReference = dynamic_cast<xmlsecurity::pdfio::PDFReferenceElement*>(pAnnots->GetElements()[0]);
+ CPPUNIT_ASSERT(pAnnotReference);
+ xmlsecurity::pdfio::PDFObjectElement* pAnnot = pAnnotReference->LookupObject();
+ CPPUNIT_ASSERT(pAnnot);
+ CPPUNIT_ASSERT_EQUAL(OString("Annot"), static_cast<xmlsecurity::pdfio::PDFNameElement*>(pAnnot->Lookup("Type"))->GetValue());
+
+ // Get the Action -> Rendition -> MediaClip -> FileSpec.
+ auto pAction = dynamic_cast<xmlsecurity::pdfio::PDFDictionaryElement*>(pAnnot->Lookup("A"));
+ CPPUNIT_ASSERT(pAction);
+ auto pRendition = dynamic_cast<xmlsecurity::pdfio::PDFDictionaryElement*>(pAction->LookupElement("R"));
+ CPPUNIT_ASSERT(pRendition);
+ auto pMediaClip = dynamic_cast<xmlsecurity::pdfio::PDFDictionaryElement*>(pRendition->LookupElement("C"));
+ CPPUNIT_ASSERT(pMediaClip);
+ auto pFileSpec = dynamic_cast<xmlsecurity::pdfio::PDFDictionaryElement*>(pMediaClip->LookupElement("D"));
+ CPPUNIT_ASSERT(pFileSpec);
+ // Make sure the filespec refers to an embedded file.
+ // This key was missing, the embedded video was handled as a linked one.
+ CPPUNIT_ASSERT(pFileSpec->LookupElement("EF"));
+}
#endif
CPPUNIT_TEST_SUITE_REGISTRATION(PdfExportTest);
diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx
index 6ffe711363c1..5dd2f0aeaa65 100644
--- a/xmlsecurity/source/pdfio/pdfdocument.cxx
+++ b/xmlsecurity/source/pdfio/pdfdocument.cxx
@@ -100,24 +100,6 @@ public:
sal_uInt64 GetLocation() const;
};
-/// Reference object: something with a unique ID.
-class PDFReferenceElement : public PDFElement
-{
- PDFDocument& m_rDoc;
- int m_fObjectValue;
- int m_fGenerationValue;
-
-public:
- PDFReferenceElement(PDFDocument& rDoc, int fObjectValue, int fGenerationValue);
- bool Read(SvStream& rStream) override;
- /// Assuming the reference points to a number object, return its value.
- double LookupNumber(SvStream& rStream) const;
- /// Lookup referenced object, without assuming anything about its contents.
- PDFObjectElement* LookupObject();
- int GetObjectValue() const;
- int GetGenerationValue() const;
-};
-
/// End of a stream: 'endstream' keyword.
class PDFEndStreamElement : public PDFElement
{
@@ -132,19 +114,6 @@ public:
bool Read(SvStream& rStream) override;
};
-/// Array object: a list.
-class PDFArrayElement : public PDFElement
-{
- /// Location after the '[' token.
- sal_uInt64 m_nOffset = 0;
- std::vector<PDFElement*> m_aElements;
-public:
- PDFArrayElement();
- bool Read(SvStream& rStream) override;
- void PushBack(PDFElement* pElement);
- const std::vector<PDFElement*>& GetElements();
-};
-
/// End of an array: ']'.
class PDFEndArrayElement : public PDFElement
{
@@ -3159,6 +3128,11 @@ PDFObjectElement* PDFDictionaryElement::LookupObject(const OString& rDictionaryK
return pKey->LookupObject();
}
+PDFElement* PDFDictionaryElement::LookupElement(const OString& rDictionaryKey)
+{
+ return PDFDictionaryElement::Lookup(m_aItems, rDictionaryKey);
+}
+
PDFElement* PDFObjectElement::Lookup(const OString& rDictionaryKey)
{
if (m_aDictionary.empty())