Author: lehmi
Date: Thu Feb  6 07:10:39 2025
New Revision: 1923602

URL: http://svn.apache.org/viewvc?rev=1923602&view=rev
Log:
PDFBOX-5945: fix SIZE entry in trailer dictionary, add test provided by Lahcen 
FTIH 

Modified:
    
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
    
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java

Modified: 
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
URL: 
http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java?rev=1923602&r1=1923601&r2=1923602&view=diff
==============================================================================
--- 
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
 (original)
+++ 
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
 Thu Feb  6 07:10:39 2025
@@ -613,17 +613,18 @@ public class COSWriter implements ICOSVi
         getStandardOutput().writeEOL();
 
         COSDictionary trailer = doc.getTrailer();
-        //sort xref, needed only if object keys not regenerated
-        Collections.sort(getXRefEntries());
-        COSWriterXRefEntry lastEntry = getXRefEntries().get( 
getXRefEntries().size()-1);
-        trailer.setLong(COSName.SIZE, lastEntry.getKey().getNumber()+1);
         // Only need to stay, if an incremental update will be performed
         if (!incrementalUpdate) 
         {
-          trailer.removeItem( COSName.PREV );
+            // sort xref, needed only if object keys not regenerated
+            Collections.sort(getXRefEntries());
+            COSWriterXRefEntry lastEntry = 
getXRefEntries().get(getXRefEntries().size() - 1);
+            trailer.setLong(COSName.SIZE, lastEntry.getKey().getNumber() + 1);
+            trailer.removeItem(COSName.PREV);
         }
         if (!doc.isXRefStream())
         {
+            trailer.setLong(COSName.SIZE, number + 1);
             trailer.removeItem( COSName.XREF_STM );
         }
         // Remove a checksum if present

Modified: 
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
URL: 
http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java?rev=1923602&r1=1923601&r2=1923602&view=diff
==============================================================================
--- 
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
 (original)
+++ 
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
 Thu Feb  6 07:10:39 2025
@@ -16,11 +16,24 @@
  */
 package org.apache.pdfbox.pdfwriter;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSDocument;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObjectKey;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
+import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
+import org.apache.pdfbox.pdmodel.interactive.form.PDTextField;
 import org.junit.Test;
 
 public class COSWriterTest
@@ -62,4 +75,91 @@ public class COSWriterTest
         }));
         doc.close();
     }
+
+    @Test
+    public void testPDFBox5945() throws Exception
+    {
+        byte[] input = create();
+        checkTrailerSize(input);
+
+        byte[] output = edit(input);
+        checkTrailerSize(output);
+    }
+
+    private static void checkTrailerSize(byte[] docData) throws IOException
+    {
+        try
+        {
+            PDDocument pdDocument = PDDocument.load(docData);
+            COSDocument cosDocument = pdDocument.getDocument();
+            long maxObjNumber = 0;
+            for (COSObjectKey key : cosDocument.getXrefTable().keySet())
+            {
+                maxObjNumber = key.getNumber() > maxObjNumber ? 
key.getNumber() : maxObjNumber;
+            }
+            long sizeFromTrailer = 
cosDocument.getTrailer().getLong(COSName.SIZE);
+            assertEquals(maxObjNumber + 1, sizeFromTrailer);
+            pdDocument.close();
+        }
+        catch (IOException exception)
+        {
+            // rethrow
+            throw exception;
+        }
+    }
+
+    private static byte[] create() throws IOException
+    {
+        try
+        {
+            PDDocument pdDocument = new PDDocument();
+            PDAcroForm acroForm = new PDAcroForm(pdDocument);
+            pdDocument.getDocumentCatalog().setAcroForm(acroForm);
+            PDResources resources = new PDResources();
+            resources.put(COSName.getPDFName("Helv"), PDType1Font.HELVETICA);
+            resources.put(COSName.getPDFName("ZaDb"), PDType1Font.SYMBOL);
+            acroForm.setDefaultResources(resources);
+            PDPage page = new PDPage(PDRectangle.A4);
+            pdDocument.addPage(page);
+            PDTextField textField = new PDTextField(acroForm);
+            textField.setPartialName("textFieldName");
+            acroForm.getFields().add(textField);
+            PDAnnotationWidget widget = textField.getWidgets().get(0);
+            widget.setPage(page);
+            page.getAnnotations().add(widget);
+            PDRectangle rectangle = new PDRectangle(10, 200, 200, 15);
+            widget.setRectangle(rectangle);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            pdDocument.save(out);
+            pdDocument.close();
+            return out.toByteArray();
+        }
+        catch (IOException exception)
+        {
+            // rethrow
+            throw exception;
+        }
+    }
+
+    private static byte[] edit(byte[] input) throws IOException
+    {
+        try 
+        {
+            PDDocument pdDocument = PDDocument.load(input);
+            PDTextField textField = (PDTextField) 
pdDocument.getDocumentCatalog().getAcroForm()
+                    .getField("textFieldName");
+            assertNotNull(textField);
+            textField.setMultiline(true);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            pdDocument.saveIncremental(out);
+            pdDocument.close();
+            return out.toByteArray();
+        }
+        catch(IOException exception)
+        {
+            // rethrow
+            throw exception;
+        }
+    }
+
 }


Reply via email to