diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2020-06-25 10:58:25 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2020-06-25 14:29:54 +0200 |
commit | 022f6bb1f7ed06edb126a2b85719d8622104bb57 (patch) | |
tree | c646fd43f4d30cba1d45ea117fac4a62273110d8 /vcl/qa | |
parent | 798f8c2efac28ff15a2f7aa5e39c3744756de5b2 (diff) |
sd signature line: place shape on the correct page
PDFDocument::Sign() had this hardcoded to always place the signature
widget on the first page, add a way so that xmlsecurity/ can tell the
pdf signing code to put it on an other page.
This way in case the user created the signature line shape on the Nth
page, it'll end up on the Nth page of the PDF result as well, as
expected.
Change-Id: I63decba98774151e9634ea924c2fed0f7814cb28
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97045
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'vcl/qa')
-rw-r--r-- | vcl/qa/cppunit/filter/ipdf/data/add-visible-signature-last-page.pdf | 111 | ||||
-rw-r--r-- | vcl/qa/cppunit/filter/ipdf/ipdf.cxx | 149 |
2 files changed, 260 insertions, 0 deletions
diff --git a/vcl/qa/cppunit/filter/ipdf/data/add-visible-signature-last-page.pdf b/vcl/qa/cppunit/filter/ipdf/data/add-visible-signature-last-page.pdf new file mode 100644 index 000000000000..c321abd0959e --- /dev/null +++ b/vcl/qa/cppunit/filter/ipdf/data/add-visible-signature-last-page.pdf @@ -0,0 +1,111 @@ +%PDF-1.6 +%äüöß +2 0 obj +<</Length 3 0 R/Filter/FlateDecode>> +stream +xTn1]K/I8Mg\\PԐnf2eڨpBIB2~#QwDɶƿ#gzKkMkRؼ7妁 ++Rw2Q#XQ˲sv`7Vܸ$}dFڜTXI+8+]HN+kC"Tta@+"]9ZYRq a!O<ҫ +d\)WiKO.H/\$ώga-/w- !9cDc +ΩPqe:/ tqi08{{N10\N9UҸAoݵӏZ/_b7F߾_a_t{!J@ACjl4#}ԍH뭷Gc;2?cQ@ +endstream +endobj + +3 0 obj +426 +endobj + +5 0 obj +<</Length 6 0 R/Filter/FlateDecode>> +stream +x;1D{qr$ZfO#Q#+r&x #Y Z}>a;zg6 +xn:d8
aQ^D,;7#M3qĵ1Ɛ$}5+'pΏ5y^qYW]ٶuL#>"B +endstream +endobj + +6 0 obj +167 +endobj + +8 0 obj +<< +>> +endobj + +9 0 obj +<</Font 8 0 R +/ProcSet[/PDF/Text] +>> +endobj + +1 0 obj +<</Type/Page/Parent 7 0 R/Resources 9 0 R/MediaBox[0 0 612 792]/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 2 0 R>> +endobj + +4 0 obj +<</Type/Page/Parent 7 0 R/Resources 9 0 R/MediaBox[0 0 612 792]/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 5 0 R>> +endobj + +10 0 obj +<</Count 2/First 11 0 R/Last 12 0 R +>> +endobj + +11 0 obj +<</Count 0/Title<FEFF005000610067006500200031> +/Dest[1 0 R/XYZ 0 792 0]/Parent 10 0 R/Next 12 0 R>> +endobj + +12 0 obj +<</Count 0/Title<FEFF005000610067006500200032> +/Dest[4 0 R/XYZ 0 792 0]/Parent 10 0 R/Prev 11 0 R>> +endobj + +7 0 obj +<</Type/Pages +/Resources 9 0 R +/MediaBox[ 0 0 612 792 ] +/Kids[ 1 0 R 4 0 R ] +/Count 2>> +endobj + +13 0 obj +<</Type/Catalog/Pages 7 0 R +/OpenAction[1 0 R /XYZ null null 0] +/Outlines 10 0 R +>> +endobj + +14 0 obj +<</Author<FEFF004D0069006B006C006F0073002000560061006A006E0061> +/Creator<FEFF0044007200610077> +/Producer<FEFF004C0069006200720065004F0066006600690063006500440065007600200037002E0031> +/CreationDate(D:20200624113559+02'00')>> +endobj + +xref +0 15 +0000000000 65535 f +0000000869 00000 n +0000000019 00000 n +0000000516 00000 n +0000001011 00000 n +0000000536 00000 n +0000000774 00000 n +0000001443 00000 n +0000000794 00000 n +0000000816 00000 n +0000001153 00000 n +0000001209 00000 n +0000001326 00000 n +0000001547 00000 n +0000001648 00000 n +trailer +<</Size 15/Root 13 0 R +/Info 14 0 R +/ID [ <F52D3902B7388C216897409EFCC78884> +<F52D3902B7388C216897409EFCC78884> ] +/DocChecksum /67E881EB92900640250E0931504CE95E +>> +startxref +1889 +%%EOF diff --git a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx new file mode 100644 index 000000000000..5d44cf9bbef2 --- /dev/null +++ b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx @@ -0,0 +1,149 @@ +/* -*- 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 <test/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> + +#include <prewin.h> +#include <cpp/fpdf_scopers.h> +#include <postwin.h> + +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/xml/crypto/SEInitializer.hpp> + +#include <comphelper/propertyvalue.hxx> +#include <osl/file.hxx> +#include <unotools/tempfile.hxx> +#include <sfx2/sfxbasemodel.hxx> +#include <svx/svdview.hxx> +#include <sfx2/viewsh.hxx> +#include <svx/signaturelinehelper.hxx> +#include <sfx2/objsh.hxx> +#include <vcl/filter/PDFiumLibrary.hxx> + +using namespace ::com::sun::star; + +namespace +{ +char const DATA_DIRECTORY[] = "/vcl/qa/cppunit/filter/ipdf/data/"; +} + +/// Covers vcl/source/filter/ipdf/ fixes. +class VclFilterIpdfTest : public test::BootstrapFixture, public unotest::MacrosTest +{ +private: + uno::Reference<lang::XComponent> mxComponent; + uno::Reference<xml::crypto::XSEInitializer> mxSEInitializer; + uno::Reference<xml::crypto::XXMLSecurityContext> mxSecurityContext; + +public: + void setUp() override; + void tearDown() override; + uno::Reference<lang::XComponent>& getComponent() { return mxComponent; } + uno::Reference<xml::crypto::XXMLSecurityContext>& getSecurityContext() + { + return mxSecurityContext; + } +}; + +void VclFilterIpdfTest::setUp() +{ + test::BootstrapFixture::setUp(); + MacrosTest::setUpNssGpg(m_directories, "vcl_filter_ipdf"); + + mxDesktop.set(frame::Desktop::create(mxComponentContext)); + mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext); + mxSecurityContext = mxSEInitializer->createSecurityContext(OUString()); +} + +void VclFilterIpdfTest::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + + MacrosTest::tearDownNssGpg(); + test::BootstrapFixture::tearDown(); +} + +CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testPDFAddVisibleSignatureLastPage) +{ + // Given: copy the test document to a temporary file, as it'll be modified. + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aSourceURL + = m_directories.getURLFromSrc(DATA_DIRECTORY) + "add-visible-signature-last-page.pdf"; + OUString aURL = aTempFile.GetURL(); + osl::File::RC eRet = osl::File::copy(aSourceURL, aURL); + CPPUNIT_ASSERT_EQUAL(osl::File::RC::E_None, eRet); + + // Open it. + uno::Sequence<beans::PropertyValue> aArgs = { comphelper::makePropertyValue("ReadOnly", true) }; + getComponent() = loadFromDesktop(aURL, "com.sun.star.drawing.DrawingDocument", aArgs); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(getComponent().get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // Add a signature line to the 2nd page. + uno::Reference<lang::XMultiServiceFactory> xFactory(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XShape> xShape( + xFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), uno::UNO_QUERY); + xShape->setPosition(awt::Point(1000, 15000)); + xShape->setSize(awt::Size(10000, 10000)); + uno::Reference<drawing::XDrawPagesSupplier> xSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPages> xDrawPages = xSupplier->getDrawPages(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xDrawPages->getCount()); + + uno::Reference<frame::XModel> xModel(getComponent(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawView> xController(xModel->getCurrentController(), uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(1), uno::UNO_QUERY); + xController->setCurrentPage(xDrawPage); + xDrawPage->add(xShape); + + // Select it and assign a certificate. + uno::Reference<view::XSelectionSupplier> xSelectionSupplier(pBaseModel->getCurrentController(), + uno::UNO_QUERY); + xSelectionSupplier->select(uno::makeAny(xShape)); + uno::Sequence<uno::Reference<security::XCertificate>> aCertificates + = getSecurityContext()->getSecurityEnvironment()->getPersonalCertificates(); + if (!aCertificates.hasElements()) + { + return; + } + SdrView* pView = SfxViewShell::Current()->GetDrawView(); + svx::SignatureLineHelper::setShapeCertificate(pView, aCertificates[0]); + + // When: do the actual signing. + pObjectShell->SignDocumentContentUsingCertificate(aCertificates[0]); + + // Then: count the # of shapes on the signature widget/annotation. + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + SvFileStream aFile(aTempFile.GetURL(), StreamMode::READ); + SvMemoryStream aMemory; + aMemory.WriteStream(aFile); + // Last page. + ScopedFPDFDocument pPdfDocument( + FPDF_LoadMemDocument(aMemory.GetData(), aMemory.GetSize(), /*password=*/nullptr)); + ScopedFPDFPage pPdfPage(FPDF_LoadPage(pPdfDocument.get(), /*page_index=*/1)); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // i.e. the signature was there, but it was on the first page. + CPPUNIT_ASSERT_EQUAL(1, FPDFPage_GetAnnotCount(pPdfPage.get())); + ScopedFPDFAnnotation pAnnot(FPDFPage_GetAnnot(pPdfPage.get(), 0)); + CPPUNIT_ASSERT_EQUAL(4, FPDFAnnot_GetObjectCount(pAnnot.get())); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |