Author: lehmi
Date: Thu Feb 6 07:07:36 2025
New Revision: 1923601
URL: http://svn.apache.org/viewvc?rev=1923601&view=rev
Log:
PDFBOX-5945: fix SIZE entry in trailer dictionary, add test provided by Lahcen
FTIH
Modified:
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
Modified:
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
URL:
http://svn.apache.org/viewvc/pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java?rev=1923601&r1=1923600&r2=1923601&view=diff
==============================================================================
---
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
(original)
+++
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java
Thu Feb 6 07:07:36 2025
@@ -685,18 +685,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/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
URL:
http://svn.apache.org/viewvc/pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java?rev=1923601&r1=1923600&r2=1923601&view=diff
==============================================================================
---
pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
(original)
+++
pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java
Thu Feb 6 07:07:36 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();
+ }
+ }
+
}