xmlsecurity/source/pdfio/pdfdocument.cxx |   37 +++++++++++++++----------------
 1 file changed, 18 insertions(+), 19 deletions(-)

New commits:
commit c21329fa904b682bde3df1082821df0af7ebbea3
Author: Miklos Vajna <vmik...@collabora.co.uk>
Date:   Thu Nov 10 10:18:31 2016 +0100

    xmlsecurity PDF verify: fix incremental updates vs object streams
    
    The problem: an object stream provies obj#1 and obj#2, then an
    incremental updates provides an updated obj#1'. Then we look up obj#2,
    parse the stored objects on-demand, so at the end when later we look up
    the first object, we find obj#1, not obj#1'.
    
    An easy workaround would be to never update already existing objects
    from object streams, but that would break when an incremental update
    provides an object stream.
    
    Fix the problem by parsing stored objects right after tokenizing the
    object stream, and not later, on-demand, when we no longer have the
    context what objects should be ignored.
    
    This is needed (but not enough) to correctly append a signature at the
    end of a PDF file that has both object streams and incremental updates.
    
    Change-Id: I3c1fae5ac26804c8e8cc1984511f43cfa881c97b

diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx 
b/xmlsecurity/source/pdfio/pdfdocument.cxx
index 58aac94..2921222 100644
--- a/xmlsecurity/source/pdfio/pdfdocument.cxx
+++ b/xmlsecurity/source/pdfio/pdfdocument.cxx
@@ -603,7 +603,7 @@ bool PDFDocument::Sign(const 
uno::Reference<security::XCertificate>& xCertificat
         SvMemoryStream* pStreamBuffer = pAcroFormObject->GetStreamBuffer();
         if (!pStreamBuffer)
         {
-            SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Sign: AcroForm object 
is in an object stream");
+            SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Sign: AcroForm object 
is not in an object stream");
             return false;
         }
 
@@ -982,6 +982,8 @@ bool PDFDocument::Tokenize(SvStream& rStream, TokenizeMode 
eMode, std::vector< s
 {
     // Last seen object token.
     PDFObjectElement* pObject = pObjectElement;
+    PDFNameElement* pObjectKey = nullptr;
+    PDFObjectElement* pObjectStream = nullptr;
     bool bInXRef = false;
     // The next number will be an xref offset.
     bool bInStartXRef = false;
@@ -1064,10 +1066,15 @@ bool PDFDocument::Tokenize(SvStream& rStream, 
TokenizeMode eMode, std::vector< s
         }
         case '/':
         {
-            rElements.push_back(std::unique_ptr<PDFElement>(new 
PDFNameElement()));
+            auto pNameElement = new PDFNameElement();
+            rElements.push_back(std::unique_ptr<PDFElement>(pNameElement));
             rStream.SeekRel(-1);
-            if (!rElements.back()->Read(rStream))
+            if (!pNameElement->Read(rStream))
                 return false;
+            if (pObject && pObjectKey && pObjectKey->GetValue() == "Type" && 
pNameElement->GetValue() == "ObjStm")
+                pObjectStream = pObject;
+            else
+                pObjectKey = pNameElement;
             break;
         }
         case '(':
@@ -1197,6 +1204,14 @@ bool PDFDocument::Tokenize(SvStream& rStream, 
TokenizeMode eMode, std::vector< s
                         // Found endobj and only object parsing was requested, 
we're done.
                         return true;
                     }
+
+                    if (pObjectStream)
+                    {
+                        // We're at the end of an object stream, parse the 
stored objects.
+                        pObjectStream->ParseStoredObjects();
+                        pObjectStream = nullptr;
+                        pObjectKey = nullptr;
+                    }
                 }
                 else if (aKeyword == "true" || aKeyword == "false")
                     rElements.push_back(std::unique_ptr<PDFElement>(new 
PDFBooleanElement(aKeyword.toBoolean())));
@@ -3096,22 +3111,6 @@ PDFObjectElement* PDFReferenceElement::LookupObject()
 PDFObjectElement* PDFDocument::LookupObject(size_t nObjectNumber)
 {
     auto itIDObjects = m_aIDObjects.find(nObjectNumber);
-    auto itXRef = m_aXRef.find(nObjectNumber);
-    if (itIDObjects == m_aIDObjects.end() && itXRef != m_aXRef.end())
-    {
-        // We don't have an object for this number yet, but there is an xref
-        // entry for it.
-        const XRefEntry& rEntry = itXRef->second;
-        if (rEntry.m_eType == XRefEntryType::COMPRESSED)
-        {
-            // It's a compressed entry, try parsing the stored objects.
-            if (PDFObjectElement* pObjectStream = 
LookupObject(rEntry.m_nOffset))
-                // This registers new IDs.
-                pObjectStream->ParseStoredObjects();
-        }
-        // Find again, now that the new objects are registered.
-        itIDObjects = m_aIDObjects.find(nObjectNumber);
-    }
 
     if (itIDObjects != m_aIDObjects.end())
         return itIDObjects->second;
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to