summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2021-09-07 13:51:20 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2021-09-08 10:09:27 +0200
commitc6b6e5b9cbb9ce78b11c26bf3d1a27c2f2cb76ac (patch)
treebe9bea13a21c4eb237df03b7453558b54daba1c0
parent7ed532a2cbce52cd20b0801116d35ce713365f76 (diff)
tdf#142129 vcl: add unit test
Reportedly bug was fixed by commit 5fc6a601d7a1978db291fd0f7dcec638a7c25651 Change-Id: Iee32cacff0c939bdf498e9dc8102eb2d22a5a1c9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121776 Tested-by: Michael Stahl <michael.stahl@allotropia.de> Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> (cherry picked from commit 992f878e8c3424f7ce96a78ccf3a316b29ffd9ec) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121763 Tested-by: Xisco Fauli <xiscofauli@libreoffice.org> Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r--include/vcl/filter/pdfdocument.hxx1
-rw-r--r--vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odtbin0 -> 25317 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/data/master.odmbin0 -> 22304 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/pdfexport.cxx87
-rw-r--r--vcl/source/filter/ipdf/pdfdocument.cxx17
5 files changed, 105 insertions, 0 deletions
diff --git a/include/vcl/filter/pdfdocument.hxx b/include/vcl/filter/pdfdocument.hxx
index 26866544bf60..4b5d732617cc 100644
--- a/include/vcl/filter/pdfdocument.hxx
+++ b/include/vcl/filter/pdfdocument.hxx
@@ -546,6 +546,7 @@ public:
//@{
/// Decode a hex dump.
static std::vector<unsigned char> DecodeHexString(PDFHexStringElement const* pElement);
+ static OUString DecodeHexStringUTF16BE(PDFHexStringElement const& rElement);
static OString ReadKeyword(SvStream& rStream);
static size_t FindStartXRef(SvStream& rStream);
void ReadXRef(SvStream& rStream);
diff --git a/vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt b/vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt
new file mode 100644
index 000000000000..05e2bb18408a
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/data/master.odm b/vcl/qa/cppunit/pdfexport/data/master.odm
new file mode 100644
index 000000000000..74016352b762
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/master.odm
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index bb203602714d..0da9bedd33ef 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -2791,6 +2791,93 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfUaMetadata)
CPPUNIT_ASSERT_EQUAL(OString("1"), aPdfUaPart);
}
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142129)
+{
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "master.odm";
+ mxComponent = loadFromDesktop(aURL);
+
+ // update linked section
+ dispatchCommand(mxComponent, ".uno:UpdateAllLinks", {});
+
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+ // Enable Outlines export
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "ExportBookmarks", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Parse the export result.
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ auto* pCatalog = aDocument.GetCatalog();
+ CPPUNIT_ASSERT(pCatalog);
+ auto* pCatalogDictionary = pCatalog->GetDictionary();
+ CPPUNIT_ASSERT(pCatalogDictionary);
+ auto* pOutlinesObject = pCatalogDictionary->LookupObject("Outlines");
+ CPPUNIT_ASSERT(pOutlinesObject);
+ auto* pOutlinesDictionary = pOutlinesObject->GetDictionary();
+#if 0
+ // Type isn't actually written currently
+ auto* pType
+ = dynamic_cast<vcl::filter::PDFNameElement*>(pOutlinesDictionary->LookupElement("Type"));
+ CPPUNIT_ASSERT(pType);
+ CPPUNIT_ASSERT_EQUAL(OString("Outlines"), pType->GetValue());
+#endif
+
+ auto* pFirst = dynamic_cast<vcl::filter::PDFReferenceElement*>(
+ pOutlinesDictionary->LookupElement("First"));
+ CPPUNIT_ASSERT(pFirst);
+ auto* pFirstD = pFirst->LookupObject()->GetDictionary();
+ CPPUNIT_ASSERT(pFirstD);
+ //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast<vcl::filter::PDFNameElement*>(pFirstD->LookupElement("Type"))->GetValue());
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Preface"), ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(
+ pFirstD->LookupElement("Title"))));
+
+ auto* pFirst1
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pFirstD->LookupElement("First"));
+ CPPUNIT_ASSERT(pFirst1);
+ auto* pFirst1D = pFirst1->LookupObject()->GetDictionary();
+ CPPUNIT_ASSERT(pFirst1D);
+ // here is a hidden section with headings "Copyright" etc.; check that
+ // there are no outline entries for it
+ //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast<vcl::filter::PDFNameElement*>(pFirst1D->LookupElement("Type"))->GetValue());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"Who is this book for?"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(pFirst1D->LookupElement("Title"))));
+
+ auto* pFirst2
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pFirst1D->LookupElement("Next"));
+ auto* pFirst2D = pFirst2->LookupObject()->GetDictionary();
+ CPPUNIT_ASSERT(pFirst2D);
+ //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast<vcl::filter::PDFNameElement*>(pFirst2D->LookupElement("Type"))->GetValue());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"What\u2019s in this book?"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(pFirst2D->LookupElement("Title"))));
+
+ auto* pFirst3
+ = dynamic_cast<vcl::filter::PDFReferenceElement*>(pFirst2D->LookupElement("Next"));
+ auto* pFirst3D = pFirst3->LookupObject()->GetDictionary();
+ CPPUNIT_ASSERT(pFirst3D);
+ //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast<vcl::filter::PDFNameElement*>(pFirst3D->LookupElement("Type"))->GetValue());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString(u"Minimum requirements for using LibreOffice"),
+ ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(
+ *dynamic_cast<vcl::filter::PDFHexStringElement*>(pFirst3D->LookupElement("Title"))));
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<vcl::filter::PDFElement*>(nullptr),
+ pFirst3D->LookupElement("Next"));
+ CPPUNIT_ASSERT_EQUAL(static_cast<vcl::filter::PDFElement*>(nullptr),
+ pFirstD->LookupElement("Next"));
+}
+
CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageRotate180)
{
// Create an empty document.
diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx
index e8bca353133d..f5fc63be558f 100644
--- a/vcl/source/filter/ipdf/pdfdocument.cxx
+++ b/vcl/source/filter/ipdf/pdfdocument.cxx
@@ -2052,6 +2052,23 @@ std::vector<unsigned char> PDFDocument::DecodeHexString(PDFHexStringElement cons
return svl::crypto::DecodeHexString(pElement->GetValue());
}
+OUString PDFDocument::DecodeHexStringUTF16BE(PDFHexStringElement const& rElement)
+{
+ std::vector<unsigned char> const encoded(DecodeHexString(&rElement));
+ // Text strings can be PDF-DocEncoding or UTF-16BE with mandatory BOM;
+ // only the latter supported is here
+ if (encoded.size() < 2 || encoded[0] != 0xFE || encoded[1] != 0xFF || (encoded.size() & 1) != 0)
+ {
+ return OUString();
+ }
+ OUStringBuffer buf(static_cast<unsigned int>(encoded.size() - 2));
+ for (size_t i = 2; i < encoded.size(); i += 2)
+ {
+ buf.append(sal_Unicode((static_cast<sal_uInt16>(encoded[i]) << 8) | encoded[i + 1]));
+ }
+ return buf.makeStringAndClear();
+}
+
PDFCommentElement::PDFCommentElement(PDFDocument& rDoc)
: m_rDoc(rDoc)
{