You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2025/02/06 07:07:12 UTC
svn commit: r1923600 - in /pdfbox/trunk/pdfbox/src: main/java/org/apache/pdfbox/pdfwriter/COSWriter.java test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
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();
+ }
+ }
+
}