Skip to content

Commit b403d12

Browse files
committed
PDFBOX-5945: fix SIZE entry in trailer dictionary, add test provided by Lahcen FTIH
git-svn-id: https://svn.apache.org/repos/asf/pdfbox/trunk@1923600 13f79535-47bb-0310-9956-ffa450edef68
1 parent 48afe5f commit b403d12

File tree

2 files changed

+88
-7
lines changed

2 files changed

+88
-7
lines changed

pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -684,18 +684,19 @@ protected void doWriteTrailer(COSDocument doc) throws IOException
684684
getStandardOutput().writeEOL();
685685

686686
COSDictionary trailer = doc.getTrailer();
687-
//sort xref, needed only if object keys not regenerated
688-
Collections.sort(getXRefEntries());
689-
XReferenceEntry lastEntry = getXRefEntries().get(getXRefEntries().size() - 1);
690-
trailer.setLong(COSName.SIZE, lastEntry.getReferencedKey().getNumber() + 1);
691687
// Only need to stay, if an incremental update will be performed
692-
if (!incrementalUpdate)
688+
if (!incrementalUpdate)
693689
{
694-
trailer.removeItem( COSName.PREV );
690+
// sort xref, needed only if object keys not regenerated
691+
Collections.sort(getXRefEntries());
692+
XReferenceEntry lastEntry = getXRefEntries().get(getXRefEntries().size() - 1);
693+
trailer.setLong(COSName.SIZE, lastEntry.getReferencedKey().getNumber() + 1);
694+
trailer.removeItem(COSName.PREV);
695695
}
696696
if (!doc.isXRefStream())
697697
{
698-
trailer.removeItem( COSName.XREF_STM );
698+
trailer.setLong(COSName.SIZE, number + 1);
699+
trailer.removeItem(COSName.XREF_STM);
699700
}
700701
// Remove a checksum if present
701702
trailer.removeItem( COSName.DOC_CHECKSUM );

pdfbox/src/test/java/org/apache/pdfbox/pdfwriter/COSWriterTest.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,31 @@
1616
*/
1717
package org.apache.pdfbox.pdfwriter;
1818

19+
import static org.junit.jupiter.api.Assertions.assertEquals;
20+
import static org.junit.jupiter.api.Assertions.assertNotNull;
21+
1922
import java.io.BufferedOutputStream;
2023
import java.io.ByteArrayOutputStream;
2124
import java.io.File;
2225
import java.io.IOException;
2326
import java.nio.file.Paths;
2427

2528
import org.apache.pdfbox.Loader;
29+
import org.apache.pdfbox.cos.COSDocument;
30+
import org.apache.pdfbox.cos.COSName;
31+
import org.apache.pdfbox.cos.COSObjectKey;
2632
import org.apache.pdfbox.multipdf.PageExtractor;
33+
import org.apache.pdfbox.pdfwriter.compress.CompressParameters;
2734
import org.apache.pdfbox.pdmodel.PDDocument;
2835
import org.apache.pdfbox.pdmodel.PDPage;
36+
import org.apache.pdfbox.pdmodel.PDResources;
37+
import org.apache.pdfbox.pdmodel.common.PDRectangle;
38+
import org.apache.pdfbox.pdmodel.font.PDFont;
39+
import org.apache.pdfbox.pdmodel.font.PDType1Font;
40+
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
41+
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
42+
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
43+
import org.apache.pdfbox.pdmodel.interactive.form.PDTextField;
2944
import org.junit.jupiter.api.Test;
3045

3146
class COSWriterTest
@@ -68,4 +83,69 @@ void testPDFBox5485() throws Exception
6883
}
6984
}
7085
}
86+
87+
@Test
88+
void testPDFBox5945() throws Exception
89+
{
90+
byte[] input = create();
91+
checkTrailerSize(input);
92+
93+
byte[] output = edit(input);
94+
checkTrailerSize(output);
95+
}
96+
97+
private static void checkTrailerSize(byte[] docData) throws IOException
98+
{
99+
try (PDDocument pdDocument = Loader.loadPDF(docData))
100+
{
101+
COSDocument cosDocument = pdDocument.getDocument();
102+
long maxObjNumber = cosDocument.getXrefTable().keySet().stream() //
103+
.mapToLong(COSObjectKey::getNumber).max().getAsLong();
104+
long sizeFromTrailer = cosDocument.getTrailer().getLong(COSName.SIZE);
105+
assertEquals(maxObjNumber + 1, sizeFromTrailer);
106+
}
107+
}
108+
109+
private static byte[] create() throws IOException
110+
{
111+
try (PDDocument pdDocument = new PDDocument())
112+
{
113+
PDAcroForm acroForm = new PDAcroForm(pdDocument);
114+
pdDocument.getDocumentCatalog().setAcroForm(acroForm);
115+
PDFont font1 = new PDType1Font(Standard14Fonts.FontName.HELVETICA);
116+
PDFont font2 = new PDType1Font(Standard14Fonts.FontName.ZAPF_DINGBATS);
117+
PDResources resources = new PDResources();
118+
resources.put(COSName.getPDFName("Helv"), font1);
119+
resources.put(COSName.getPDFName("ZaDb"), font2);
120+
acroForm.setDefaultResources(resources);
121+
PDPage page = new PDPage(PDRectangle.A4);
122+
pdDocument.addPage(page);
123+
PDTextField textField = new PDTextField(acroForm);
124+
textField.setPartialName("textFieldName");
125+
acroForm.getFields().add(textField);
126+
PDAnnotationWidget widget = textField.getWidgets().get(0);
127+
widget.setPage(page);
128+
page.getAnnotations().add(widget);
129+
PDRectangle rectangle = new PDRectangle(10, 200, 200, 15);
130+
widget.setRectangle(rectangle);
131+
ByteArrayOutputStream out = new ByteArrayOutputStream();
132+
pdDocument.save(out, CompressParameters.NO_COMPRESSION);
133+
return out.toByteArray();
134+
}
135+
}
136+
137+
private static byte[] edit(byte[] input) throws IOException
138+
{
139+
try (PDDocument pdDocument = Loader.loadPDF(input))
140+
{
141+
PDTextField textField = (PDTextField) pdDocument.getDocumentCatalog().getAcroForm()
142+
.getField("textFieldName");
143+
assertNotNull(textField);
144+
textField.setMultiline(true);
145+
ByteArrayOutputStream out = new ByteArrayOutputStream();
146+
pdDocument.saveIncremental(out);
147+
return out.toByteArray();
148+
}
149+
}
150+
71151
}

0 commit comments

Comments
 (0)