include/vcl/filter/pdfdocument.hxx | 10 +++- vcl/source/filter/ipdf/pdfdocument.cxx | 77 ++++++++++++++++++++++++++++++--- 2 files changed, 79 insertions(+), 8 deletions(-)
New commits: commit 20af2146c786d90b8d9626195a2e7abaa8371750 Author: Miklos Vajna <[email protected]> AuthorDate: Wed Jun 17 16:05:36 2020 +0200 Commit: Miklos Vajna <[email protected]> CommitDate: Mon Jun 29 09:08:40 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. (cherry picked from commit 4db25ccc736185c304f1bd090b8539868932700a) Conflicts: include/vcl/filter/pdfdocument.hxx Change-Id: Ifb2e0ebf7b3514ee027701b9bf360a0c996cdc82 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97246 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/include/vcl/filter/pdfdocument.hxx b/include/vcl/filter/pdfdocument.hxx index e95fb25a7408..10ce81afa5be 100644 --- a/include/vcl/filter/pdfdocument.hxx +++ b/include/vcl/filter/pdfdocument.hxx @@ -47,6 +47,11 @@ template <class interface_type> class Reference; } } +namespace tools +{ +class Rectangle; +} + namespace vcl { namespace filter @@ -373,10 +378,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 0a02fe34bc48..2d98250bf3ae 100644 --- a/vcl/source/filter/ipdf/pdfdocument.cxx +++ b/vcl/source/filter/ipdf/pdfdocument.cxx @@ -232,8 +232,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. @@ -245,14 +299,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(); @@ -266,7 +325,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()); @@ -803,7 +866,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]) @@ -813,7 +877,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 [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
