Author: lehmi
Date: Thu Feb  6 07:07:12 2025
New Revision: 1923600

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

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

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

Modified: 
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java?rev=1923600&r1=1923599&r2=1923600&view=diff
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
 (original)
+++ 
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
 Thu Feb  6 07:07:12 2025
@@ -16,6 +16,9 @@
  */
 package org.apache.pdfbox.pdfwriter;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -23,9 +26,21 @@ import java.io.IOException;
 import java.nio.file.Paths;
 
 import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.cos.COSDocument;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObjectKey;
 import org.apache.pdfbox.multipdf.PageExtractor;
+import org.apache.pdfbox.pdfwriter.compress.CompressParameters;
 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.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
+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.jupiter.api.Test;
 
 class COSWriterTest
@@ -68,4 +83,69 @@ class COSWriterTest
             }
         }
     }
+
+    @Test
+    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 = Loader.loadPDF(docData))
+        {
+            COSDocument cosDocument = pdDocument.getDocument();
+            long maxObjNumber = cosDocument.getXrefTable().keySet().stream() //
+                    .mapToLong(COSObjectKey::getNumber).max().getAsLong();
+            long sizeFromTrailer = 
cosDocument.getTrailer().getLong(COSName.SIZE);
+            assertEquals(maxObjNumber + 1, sizeFromTrailer);
+        }
+    }
+
+    private static byte[] create() throws IOException
+    {
+        try (PDDocument pdDocument = new PDDocument())
+        {
+            PDAcroForm acroForm = new PDAcroForm(pdDocument);
+            pdDocument.getDocumentCatalog().setAcroForm(acroForm);
+            PDFont font1 = new PDType1Font(Standard14Fonts.FontName.HELVETICA);
+            PDFont font2 = new 
PDType1Font(Standard14Fonts.FontName.ZAPF_DINGBATS);
+            PDResources resources = new PDResources();
+            resources.put(COSName.getPDFName("Helv"), font1);
+            resources.put(COSName.getPDFName("ZaDb"), font2);
+            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, CompressParameters.NO_COMPRESSION);
+            return out.toByteArray();
+        }
+    }
+
+    private static byte[] edit(byte[] input) throws IOException
+    {
+        try (PDDocument pdDocument = Loader.loadPDF(input))
+        {
+            PDTextField textField = (PDTextField) 
pdDocument.getDocumentCatalog().getAcroForm()
+                    .getField("textFieldName");
+            assertNotNull(textField);
+            textField.setMultiline(true);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            pdDocument.saveIncremental(out);
+            return out.toByteArray();
+        }
+    }
+
 }


Reply via email to