include/vcl/filter/pdfdocument.hxx | 10 +++- vcl/source/filter/ipdf/pdfdocument.cxx | 77 ++++++++++++++++++++++++++++++--- 2 files changed, 79 insertions(+), 8 deletions(-)
New commits: commit 4db25ccc736185c304f1bd090b8539868932700a Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Jun 17 16:05:36 2020 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jun 17 17:34:51 2020 +0200 sd signature line: implement non-empty geometry during pdf sign Parse the pdf output which contains just the signature line shape on a page, take the same from it and use it at both places where previously the position / size was just a stub. Change-Id: Ifb2e0ebf7b3514ee027701b9bf360a0c996cdc82 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96540 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/include/vcl/filter/pdfdocument.hxx b/include/vcl/filter/pdfdocument.hxx index 8700e4892df2..aaf64ae908fe 100644 --- a/include/vcl/filter/pdfdocument.hxx +++ b/include/vcl/filter/pdfdocument.hxx @@ -29,6 +29,11 @@ namespace com::sun::star::uno template <class interface_type> class Reference; } +namespace tools +{ +class Rectangle; +} + namespace vcl::filter { class PDFTrailerElement; @@ -353,10 +358,11 @@ class VCL_DLLPUBLIC PDFDocument sal_Int32 WriteSignatureObject(const OUString& rDescription, bool bAdES, sal_uInt64& rLastByteRangeOffset, sal_Int64& rContentOffset); /// Write the appearance object as part of signing. - sal_Int32 WriteAppearanceObject(); + sal_Int32 WriteAppearanceObject(tools::Rectangle& rSignatureRectangle); /// Write the annot object as part of signing. sal_Int32 WriteAnnotObject(PDFObjectElement const& rFirstPage, sal_Int32 nSignatureId, - sal_Int32 nAppearanceId); + sal_Int32 nAppearanceId, + const tools::Rectangle& rSignatureRectangle); /// Write the updated Page object as part of signing. bool WritePageObject(PDFObjectElement& rFirstPage, sal_Int32 nAnnotId); /// Write the updated Catalog object as part of signing. diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx index 316b8c74d169..928f22d8a8c7 100644 --- a/vcl/source/filter/ipdf/pdfdocument.cxx +++ b/vcl/source/filter/ipdf/pdfdocument.cxx @@ -236,8 +236,62 @@ sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, bool b return nSignatureId; } -sal_Int32 PDFDocument::WriteAppearanceObject() +sal_Int32 PDFDocument::WriteAppearanceObject(tools::Rectangle& rSignatureRectangle) { + if (!m_aSignatureLine.empty()) + { + // Parse the PDF data of signature line: we can set the signature rectangle to non-empty + // based on it. + SvMemoryStream aPDFStream; + aPDFStream.WriteBytes(m_aSignatureLine.data(), m_aSignatureLine.size()); + aPDFStream.Seek(0); + filter::PDFDocument aPDFDocument; + if (!aPDFDocument.Read(aPDFStream)) + { + SAL_WARN("vcl.filter", + "PDFDocument::WriteAppearanceObject: failed to read the PDF document"); + return -1; + } + + std::vector<filter::PDFObjectElement*> aPages = aPDFDocument.GetPages(); + if (aPages.empty()) + { + SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: no pages"); + return -1; + } + + filter::PDFObjectElement* pPage = aPages[0]; + if (!pPage) + { + SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: no page"); + return -1; + } + + // Calculate the bounding box. + PDFElement* pMediaBox = pPage->Lookup("MediaBox"); + auto pMediaBoxArray = dynamic_cast<PDFArrayElement*>(pMediaBox); + if (!pMediaBoxArray || pMediaBoxArray->GetElements().size() < 4) + { + SAL_WARN("vcl.filter", + "PDFDocument::WriteAppearanceObject: MediaBox is not an array of 4"); + return -1; + } + const std::vector<PDFElement*>& rMediaBoxElements = pMediaBoxArray->GetElements(); + auto pWidth = dynamic_cast<PDFNumberElement*>(rMediaBoxElements[2]); + if (!pWidth) + { + SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: MediaBox has no width"); + return -1; + } + rSignatureRectangle.setWidth(pWidth->GetValue()); + auto pHeight = dynamic_cast<PDFNumberElement*>(rMediaBoxElements[3]); + if (!pHeight) + { + SAL_WARN("vcl.filter", "PDFDocument::WriteAppearanceObject: MediaBox has no height"); + return -1; + } + rSignatureRectangle.setHeight(pHeight->GetValue()); + } m_aSignatureLine.clear(); // Write appearance object. @@ -249,14 +303,19 @@ sal_Int32 PDFDocument::WriteAppearanceObject() m_aEditBuffer.WriteUInt32AsString(nAppearanceId); m_aEditBuffer.WriteCharPtr(" 0 obj\n"); m_aEditBuffer.WriteCharPtr("<</Type/XObject\n/Subtype/Form\n"); - m_aEditBuffer.WriteCharPtr("/BBox[0 0 0 0]\n/Length 0\n>>\n"); + m_aEditBuffer.WriteCharPtr("/BBox[0 0 "); + m_aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getWidth())); + m_aEditBuffer.WriteCharPtr(" "); + m_aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getHeight())); + m_aEditBuffer.WriteCharPtr("]\n/Length 0\n>>\n"); m_aEditBuffer.WriteCharPtr("stream\n\nendstream\nendobj\n\n"); return nAppearanceId; } sal_Int32 PDFDocument::WriteAnnotObject(PDFObjectElement const& rFirstPage, sal_Int32 nSignatureId, - sal_Int32 nAppearanceId) + sal_Int32 nAppearanceId, + const tools::Rectangle& rSignatureRectangle) { // Decide what identifier to use for the new signature. sal_uInt32 nNextSignature = GetNextSignature(); @@ -270,7 +329,11 @@ sal_Int32 PDFDocument::WriteAnnotObject(PDFObjectElement const& rFirstPage, sal_ m_aEditBuffer.WriteUInt32AsString(nAnnotId); m_aEditBuffer.WriteCharPtr(" 0 obj\n"); m_aEditBuffer.WriteCharPtr("<</Type/Annot/Subtype/Widget/F 132\n"); - m_aEditBuffer.WriteCharPtr("/Rect[0 0 0 0]\n"); + m_aEditBuffer.WriteCharPtr("/Rect[0 0 "); + m_aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getWidth())); + m_aEditBuffer.WriteCharPtr(" "); + m_aEditBuffer.WriteOString(OString::number(rSignatureRectangle.getHeight())); + m_aEditBuffer.WriteCharPtr("]\n"); m_aEditBuffer.WriteCharPtr("/FT/Sig\n"); m_aEditBuffer.WriteCharPtr("/P "); m_aEditBuffer.WriteUInt32AsString(rFirstPage.GetObjectValue()); @@ -807,7 +870,8 @@ bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificat sal_Int32 nSignatureId = WriteSignatureObject( rDescription, bAdES, nSignatureLastByteRangeOffset, nSignatureContentOffset); - sal_Int32 nAppearanceId = WriteAppearanceObject(); + tools::Rectangle aSignatureRectangle; + sal_Int32 nAppearanceId = WriteAppearanceObject(aSignatureRectangle); std::vector<PDFObjectElement*> aPages = GetPages(); if (aPages.empty() || !aPages[0]) @@ -817,7 +881,8 @@ bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificat } PDFObjectElement& rFirstPage = *aPages[0]; - sal_Int32 nAnnotId = WriteAnnotObject(rFirstPage, nSignatureId, nAppearanceId); + sal_Int32 nAnnotId + = WriteAnnotObject(rFirstPage, nSignatureId, nAppearanceId, aSignatureRectangle); if (!WritePageObject(rFirstPage, nAnnotId)) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits