Skip to content

Commit 1b9cbd6

Browse files
authored
Upgrade PDFBox API to 2.0.25 (#427)
1 parent 916e3e2 commit 1b9cbd6

File tree

142 files changed

+1762
-1312
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

142 files changed

+1762
-1312
lines changed

library/src/androidTest/java/com/tom_roush/pdfbox/encryption/TestPublicKeyEncryption.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,50 @@ public void testReadPubkeyEncryptedAES256() throws IOException
379379
is.close();
380380
doc.close();
381381
}
382-
}
382+
383+
/**
384+
* PDFBOX-5249: Read a file encrypted with AES128 but not with PDFBox, and with exposed
385+
* Metadata.
386+
*
387+
* @throws IOException
388+
*/
389+
@Test
390+
public void testReadPubkeyEncryptedAES128withMetadataExposed() throws IOException
391+
{
392+
InputStream is = testContext.getAssets().open(path + "AES128ExposedMeta.pdf");
393+
PDDocument doc = PDDocument.load(is, "",
394+
testContext.getAssets().open(path + "PDFBOX-5249.p12"), "test",
395+
MemoryUsageSetting.setupMainMemoryOnly());
396+
Assert.assertEquals("PublicKeySecurityHandler",
397+
doc.getEncryption().getSecurityHandler().getClass().getSimpleName());
398+
Assert.assertEquals(128, doc.getEncryption().getSecurityHandler().getKeyLength());
399+
PDFTextStripper stripper = new PDFTextStripper();
400+
stripper.setLineSeparator("\n");
401+
Assert.assertEquals("AES key length: 128\nwith exposed Metadata", stripper.getText(doc).trim());
402+
doc.close();
403+
is.close();
404+
}
405+
406+
/**
407+
* PDFBOX-5249: Read a file encrypted with AES128 but not with PDFBox, and with exposed
408+
* Metadata.
409+
*
410+
* @throws IOException
411+
*/
412+
@Test
413+
public void testReadPubkeyEncryptedAES256withMetadataExposed() throws IOException
414+
{
415+
InputStream is = testContext.getAssets().open(path + "AES256ExposedMeta.pdf");
416+
PDDocument doc = PDDocument.load(is, "",
417+
testContext.getAssets().open(path + "PDFBOX-5249.p12"), "test",
418+
MemoryUsageSetting.setupMainMemoryOnly());
419+
Assert.assertEquals("PublicKeySecurityHandler",
420+
doc.getEncryption().getSecurityHandler().getClass().getSimpleName());
421+
Assert.assertEquals(256, doc.getEncryption().getSecurityHandler().getKeyLength());
422+
PDFTextStripper stripper = new PDFTextStripper();
423+
stripper.setLineSeparator("\n");
424+
Assert.assertEquals("AES key length: 256 \nwith exposed Metadata", stripper.getText(doc).trim());
425+
doc.close();
426+
is.close();
427+
}
428+
}

library/src/androidTest/java/com/tom_roush/pdfbox/multipdf/PDFMergerUtilityTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,6 @@ public void testFileDeletion() throws IOException
750750
/**
751751
* Check that there is a top level Document and Parts below in a merge of 2 documents.
752752
*
753-
* @param file
754753
* @throws IOException
755754
*/
756755
public void testPDFBox5198_2() throws IOException
@@ -767,7 +766,6 @@ public void testPDFBox5198_2() throws IOException
767766
/**
768767
* Check that there is a top level Document and Parts below in a merge of 3 documents.
769768
*
770-
* @param file
771769
* @throws IOException
772770
*/
773771
public void testPDFBox5198_3() throws IOException

library/src/androidTest/java/com/tom_roush/pdfbox/pdmodel/font/PDFontTest.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import com.tom_roush.pdfbox.text.PDFTextStripper;
5252

5353
import org.junit.Assert;
54+
import org.junit.Assume;
5455
import org.junit.Before;
5556
import org.junit.Test;
5657

@@ -227,11 +228,7 @@ public void testFullEmbeddingTTC() throws IOException
227228
break;
228229
}
229230
}
230-
if (ttc == null)
231-
{
232-
Log.i("PdfBox-Android", "testFullEmbeddingTTC skipped, no .ttc files available");
233-
return;
234-
}
231+
Assume.assumeTrue("testFullEmbeddingTTC skipped, no .ttc files available", ttc != null);
235232

236233
final List<String> names = new ArrayList<String>();
237234
ttc.processAllFonts(new TrueTypeCollection.TrueTypeFontProcessor()

library/src/androidTest/java/com/tom_roush/pdfbox/pdmodel/interactive/form/AlignmentTest.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,58 +57,58 @@ public void setUp() throws IOException
5757
@Test
5858
public void fillFields() throws IOException
5959
{
60-
PDTextField field = (PDTextField) acroForm.getField("AlignLeft");
60+
PDField field = acroForm.getField("AlignLeft");
6161
field.setValue(TEST_VALUE);
6262

63-
field = (PDTextField) acroForm.getField("AlignLeft-Border_Small");
63+
field = acroForm.getField("AlignLeft-Border_Small");
6464
field.setValue(TEST_VALUE);
6565

66-
field = (PDTextField) acroForm.getField("AlignLeft-Border_Medium");
66+
field = acroForm.getField("AlignLeft-Border_Medium");
6767
field.setValue(TEST_VALUE);
6868

69-
field = (PDTextField) acroForm.getField("AlignLeft-Border_Wide");
69+
field = acroForm.getField("AlignLeft-Border_Wide");
7070
field.setValue(TEST_VALUE);
7171

72-
field = (PDTextField) acroForm.getField("AlignLeft-Border_Wide_Clipped");
72+
field = acroForm.getField("AlignLeft-Border_Wide_Clipped");
7373
field.setValue(TEST_VALUE);
7474

75-
field = (PDTextField) acroForm.getField("AlignLeft-Border_Small_Outside");
75+
field = acroForm.getField("AlignLeft-Border_Small_Outside");
7676
field.setValue(TEST_VALUE);
7777

78-
field = (PDTextField) acroForm.getField("AlignMiddle");
78+
field = acroForm.getField("AlignMiddle");
7979
field.setValue(TEST_VALUE);
8080

81-
field = (PDTextField) acroForm.getField("AlignMiddle-Border_Small");
81+
field = acroForm.getField("AlignMiddle-Border_Small");
8282
field.setValue(TEST_VALUE);
8383

84-
field = (PDTextField) acroForm.getField("AlignMiddle-Border_Medium");
84+
field = acroForm.getField("AlignMiddle-Border_Medium");
8585
field.setValue(TEST_VALUE);
8686

87-
field = (PDTextField) acroForm.getField("AlignMiddle-Border_Wide");
87+
field = acroForm.getField("AlignMiddle-Border_Wide");
8888
field.setValue(TEST_VALUE);
8989

90-
field = (PDTextField) acroForm.getField("AlignMiddle-Border_Wide_Clipped");
90+
field = acroForm.getField("AlignMiddle-Border_Wide_Clipped");
9191
field.setValue(TEST_VALUE);
9292

93-
field = (PDTextField) acroForm.getField("AlignMiddle-Border_Medium_Outside");
93+
field = acroForm.getField("AlignMiddle-Border_Medium_Outside");
9494
field.setValue(TEST_VALUE);
9595

96-
field = (PDTextField) acroForm.getField("AlignRight");
96+
field = acroForm.getField("AlignRight");
9797
field.setValue(TEST_VALUE);
9898

99-
field = (PDTextField) acroForm.getField("AlignRight-Border_Small");
99+
field = acroForm.getField("AlignRight-Border_Small");
100100
field.setValue(TEST_VALUE);
101101

102-
field = (PDTextField) acroForm.getField("AlignRight-Border_Medium");
102+
field = acroForm.getField("AlignRight-Border_Medium");
103103
field.setValue(TEST_VALUE);
104104

105-
field = (PDTextField) acroForm.getField("AlignRight-Border_Wide");
105+
field = acroForm.getField("AlignRight-Border_Wide");
106106
field.setValue(TEST_VALUE);
107107

108-
field = (PDTextField) acroForm.getField("AlignRight-Border_Wide_Clipped");
108+
field = acroForm.getField("AlignRight-Border_Wide_Clipped");
109109
field.setValue(TEST_VALUE);
110110

111-
field = (PDTextField) acroForm.getField("AlignRight-Border_Wide_Outside");
111+
field = acroForm.getField("AlignRight-Border_Wide_Outside");
112112
field.setValue(TEST_VALUE);
113113

114114
// compare rendering
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.tom_roush.pdfbox.pdmodel.interactive.form;
18+
19+
import android.content.Context;
20+
21+
import androidx.test.platform.app.InstrumentationRegistry;
22+
23+
import java.io.File;
24+
import java.io.IOException;
25+
26+
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader;
27+
import com.tom_roush.pdfbox.pdmodel.PDDocument;
28+
import com.tom_roush.pdfbox.rendering.TestRendering;
29+
30+
import org.junit.Before;
31+
import org.junit.Test;
32+
33+
/**
34+
*
35+
* @author Tilman Hausherr
36+
*/
37+
public class CombAlignmentTest
38+
{
39+
private static File OUT_DIR;
40+
private static final String IN_DIR = "pdfbox/com/tom_roush/pdfbox/pdmodel/interactive/form";
41+
private static final String NAME_OF_PDF = "CombTest.pdf";
42+
private static final String TEST_VALUE = "1234567";
43+
44+
private Context testContext;
45+
46+
@Before
47+
public void setUp() throws IOException
48+
{
49+
testContext = InstrumentationRegistry.getInstrumentation().getContext();
50+
PDFBoxResourceLoader.init(testContext);
51+
OUT_DIR = new File(testContext.getCacheDir(), "pdfbox-test-output/interactive");
52+
OUT_DIR.mkdirs();
53+
}
54+
55+
// PDFBOX-5256
56+
@Test
57+
public void testCombFields() throws IOException
58+
{
59+
PDDocument document = PDDocument.load(testContext.getAssets().open(IN_DIR + "/" + NAME_OF_PDF));
60+
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
61+
PDField field = acroForm.getField("PDFBoxCombLeft");
62+
field.setValue(TEST_VALUE);
63+
field = acroForm.getField("PDFBoxCombMiddle");
64+
field.setValue(TEST_VALUE);
65+
field = acroForm.getField("PDFBoxCombRight");
66+
field.setValue(TEST_VALUE);
67+
// compare rendering
68+
File file = new File(OUT_DIR, NAME_OF_PDF);
69+
document.save(file);
70+
document.close();
71+
TestRendering testRendering = new TestRendering();
72+
testRendering.setUp();
73+
testRendering.render(file);
74+
}
75+
}

library/src/main/java/com/tom_roush/fontbox/cff/CFFParser.java

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,10 @@ private CFFFont parseFont(CFFDataInput input, String name, byte[] topDictIndex)
437437
{
438438
CFFCIDFont cffCIDFont = new CFFCIDFont();
439439
DictData.Entry rosEntry = topDict.getEntry("ROS");
440+
if (rosEntry == null || rosEntry.size() < 3)
441+
{
442+
throw new IOException("ROS entry must have 3 elements");
443+
}
440444
cffCIDFont.setRegistry(readString(rosEntry.getNumber(0).intValue()));
441445
cffCIDFont.setOrdering(readString(rosEntry.getNumber(1).intValue()));
442446
cffCIDFont.setSupplement(rosEntry.getNumber(2).intValue());
@@ -476,14 +480,18 @@ private CFFFont parseFont(CFFDataInput input, String name, byte[] topDictIndex)
476480

477481
// charstrings index
478482
DictData.Entry charStringsEntry = topDict.getEntry("CharStrings");
483+
if (charStringsEntry == null || !charStringsEntry.hasOperands())
484+
{
485+
throw new IOException("CharStrings is missing or empty");
486+
}
479487
int charStringsOffset = charStringsEntry.getNumber(0).intValue();
480488
input.setPosition(charStringsOffset);
481489
byte[][] charStringsIndex = readIndexData(input);
482490

483491
// charset
484492
DictData.Entry charsetEntry = topDict.getEntry("charset");
485493
CFFCharset charset;
486-
if (charsetEntry != null)
494+
if (charsetEntry != null && charsetEntry.hasOperands())
487495
{
488496
int charsetId = charsetEntry.getNumber(0).intValue();
489497
if (!isCIDFont && charsetId == 0)
@@ -602,7 +610,7 @@ private void parseCIDFontDicts(CFFDataInput input, DictData topDict, CFFCIDFont
602610
// In a CIDKeyed Font, the Private dictionary isn't in the Top Dict but in the Font dict
603611
// which can be accessed by a lookup using FDArray and FDSelect
604612
DictData.Entry fdArrayEntry = topDict.getEntry("FDArray");
605-
if (fdArrayEntry == null)
613+
if (fdArrayEntry == null || !fdArrayEntry.hasOperands())
606614
{
607615
throw new IOException("FDArray is missing for a CIDKeyed Font.");
608616
}
@@ -626,7 +634,7 @@ private void parseCIDFontDicts(CFFDataInput input, DictData topDict, CFFCIDFont
626634

627635
// read private dict
628636
DictData.Entry privateEntry = fontDict.getEntry("Private");
629-
if (privateEntry == null)
637+
if (privateEntry == null || privateEntry.size() < 2)
630638
{
631639
throw new IOException("Font DICT invalid without \"Private\" entry");
632640
}
@@ -650,16 +658,20 @@ private void parseCIDFontDicts(CFFDataInput input, DictData topDict, CFFCIDFont
650658
privateDictionaries.add(privDict);
651659

652660
// local subrs
653-
int localSubrOffset = (Integer) privateDict.getNumber("Subrs", 0);
654-
if (localSubrOffset > 0)
661+
Number localSubrOffset = privateDict.getNumber("Subrs", 0);
662+
if (localSubrOffset instanceof Integer && ((Integer) localSubrOffset) > 0)
655663
{
656-
input.setPosition(privateOffset + localSubrOffset);
664+
input.setPosition(privateOffset + (Integer) localSubrOffset);
657665
privDict.put("Subrs", readIndexData(input));
658666
}
659667
}
660668

661669
// font-dict (FD) select
662670
DictData.Entry fdSelectEntry = topDict.getEntry("FDSelect");
671+
if (fdSelectEntry == null || !fdSelectEntry.hasOperands())
672+
{
673+
throw new IOException("FDSelect is missing or empty");
674+
}
663675
int fdSelectPos = fdSelectEntry.getNumber(0).intValue();
664676
input.setPosition(fdSelectPos);
665677
FDSelect fdSelect = readFDSelect(input, nrOfcharStrings, font);
@@ -705,7 +717,8 @@ private void parseType1Dicts(CFFDataInput input, DictData topDict, CFFType1Font
705717
// encoding
706718
DictData.Entry encodingEntry = topDict.getEntry("Encoding");
707719
CFFEncoding encoding;
708-
int encodingId = encodingEntry != null ? encodingEntry.getNumber(0).intValue() : 0;
720+
int encodingId = encodingEntry != null && encodingEntry.hasOperands() ?
721+
encodingEntry.getNumber(0).intValue() : 0;
709722
switch (encodingId)
710723
{
711724
case 0:
@@ -723,7 +736,7 @@ private void parseType1Dicts(CFFDataInput input, DictData topDict, CFFType1Font
723736

724737
// read private dict
725738
DictData.Entry privateEntry = topDict.getEntry("Private");
726-
if (privateEntry == null)
739+
if (privateEntry == null || privateEntry.size() < 2)
727740
{
728741
throw new IOException("Private dictionary entry missing for font " + font.fontName);
729742
}
@@ -740,10 +753,10 @@ private void parseType1Dicts(CFFDataInput input, DictData topDict, CFFType1Font
740753
}
741754

742755
// local subrs
743-
int localSubrOffset = (Integer) privateDict.getNumber("Subrs", 0);
744-
if (localSubrOffset > 0)
756+
Number localSubrOffset = privateDict.getNumber("Subrs", 0);
757+
if (localSubrOffset instanceof Integer && ((Integer) localSubrOffset) > 0)
745758
{
746-
input.setPosition(privateOffset + localSubrOffset);
759+
input.setPosition(privateOffset + (Integer) localSubrOffset);
747760
font.addToPrivateDict("Subrs", readIndexData(input));
748761
}
749762
}
@@ -768,7 +781,7 @@ private String readString(int index)
768781
private String getString(DictData dict, String name)
769782
{
770783
DictData.Entry entry = dict.getEntry(name);
771-
return entry != null ? readString(entry.getNumber(0).intValue()) : null;
784+
return entry != null && entry.hasOperands() ? readString(entry.getNumber(0).intValue()) : null;
772785
}
773786

774787
private CFFEncoding readEncoding(CFFDataInput dataInput, CFFCharset charset) throws IOException
@@ -1224,6 +1237,11 @@ public Number getNumber(int index)
12241237
return operands.get(index);
12251238
}
12261239

1240+
public int size()
1241+
{
1242+
return operands.size();
1243+
}
1244+
12271245
public Boolean getBoolean(int index)
12281246
{
12291247
Number operand = operands.get(index);
@@ -1242,6 +1260,11 @@ public Boolean getBoolean(int index)
12421260
throw new IllegalArgumentException();
12431261
}
12441262

1263+
public boolean hasOperands()
1264+
{
1265+
return !operands.isEmpty();
1266+
}
1267+
12451268
public List<Number> getArray()
12461269
{
12471270
return operands;

library/src/main/java/com/tom_roush/fontbox/cff/DataInput.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
public class DataInput
3030
{
3131

32-
private byte[] inputBuffer = null;
32+
private final byte[] inputBuffer;
3333
private int bufferPosition = 0;
3434

3535
/**

0 commit comments

Comments
 (0)