Skip to content

Commit 0538efa

Browse files
authored
Upgrade PDFBox API to v2.0.12 (#349)
1 parent 211c9ae commit 0538efa

File tree

77 files changed

+1720
-721
lines changed

Some content is hidden

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

77 files changed

+1720
-721
lines changed

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import javax.crypto.Cipher;
3636

3737
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader;
38+
import com.tom_roush.pdfbox.android.TestResourceGenerator;
3839
import com.tom_roush.pdfbox.io.IOUtils;
3940
import com.tom_roush.pdfbox.pdmodel.PDDocument;
4041
import com.tom_roush.pdfbox.pdmodel.PDDocumentCatalog;
@@ -54,6 +55,8 @@
5455

5556
import junit.framework.TestCase;
5657

58+
import static org.junit.Assume.assumeNotNull;
59+
5760
/**
5861
* Tests for symmetric key encryption.
5962
*
@@ -217,6 +220,33 @@ public void testProtection() throws Exception
217220
USERPASSWORD, OWNERPASSWORD, permission);
218221
}
219222

223+
/**
224+
* PDFBOX-4308: test that index colorspace table string doesn't get
225+
* corrupted when encrypting. This happened because the colorspace was
226+
* referenced twice, once in the resources dictionary and once in an image
227+
* in the resources dictionary, and when saving the PDF the string was saved
228+
* twice, once as a direct object and once as an indirect object (both from
229+
* the same java object). Encryption used the wrong object number and/or the
230+
* object was encrypted twice.
231+
*
232+
* @throws IOException
233+
*/
234+
public void testPDFBox4308() throws IOException
235+
{
236+
File TARGETPDFDIR = new File(testContext.getCacheDir(), "pdfs");
237+
TARGETPDFDIR.mkdirs();
238+
File pdfFile = TestResourceGenerator.downloadTestResource(TARGETPDFDIR, "PDFBOX-4308.pdf", "https://issues.apache.org/jira/secure/attachment/12938094/Quelldatei.pdf");
239+
assumeNotNull(pdfFile);
240+
241+
InputStream is = new FileInputStream(pdfFile);
242+
byte[] inputFileAsByteArray = IOUtils.toByteArray(is);
243+
is.close();
244+
int sizePriorToEncryption = inputFileAsByteArray.length;
245+
246+
testSymmEncrForKeySize(40, false, sizePriorToEncryption, inputFileAsByteArray,
247+
USERPASSWORD, OWNERPASSWORD, permission);
248+
}
249+
220250
/**
221251
* Protect a document with an embedded PDF with a key and try to reopen it
222252
* with that key and compare.

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,32 @@ public void testPDFBOX4115() throws IOException
178178
doc.close();
179179
}
180180

181+
/**
182+
* Test whether bug from PDFBOX-4318 is fixed, which had the wrong cache key.
183+
* @throws java.io.IOException
184+
*/
185+
@Test
186+
public void testPDFox4318() throws IOException
187+
{
188+
try
189+
{
190+
PDType1Font.HELVETICA_BOLD.encode("\u0080");
191+
Assert.fail("should have thrown IllegalArgumentException");
192+
}
193+
catch (IllegalArgumentException ex)
194+
{
195+
}
196+
PDType1Font.HELVETICA_BOLD.encode("€");
197+
try
198+
{
199+
PDType1Font.HELVETICA_BOLD.encode("\u0080");
200+
Assert.fail("should have thrown IllegalArgumentException");
201+
}
202+
catch (IllegalArgumentException ex)
203+
{
204+
}
205+
}
206+
181207
private void testPDFBox3826checkFonts(byte[] byteArray, File fontFile) throws IOException
182208
{
183209
PDDocument doc = PDDocument.load(byteArray);

library/src/androidTest/java/com/tom_roush/pdfbox/pdmodel/graphics/image/JPEGFactoryTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public void testCreateFromStream256() throws IOException
108108
InputStream stream = testContext.getAssets().open(
109109
"pdfbox/com/tom_roush/pdfbox/pdmodel/graphics/image/jpeg256.jpg");
110110
PDImageXObject ximage = JPEGFactory.createFromStream(document, stream);
111-
validate(ximage, 8, 344, 287, "jpg", PDDeviceGray.INSTANCE.getName());
111+
validate(ximage, 8, 344, 287, "jpg", PDDeviceRGB.INSTANCE.getName()); // TODO: PdfBox-Android
112112

113113
doWritePDF(document, ximage, testResultsDir, "jpeg256stream.pdf");
114114
checkJpegStream(testResultsDir, "jpeg256stream.pdf", testContext.getAssets().open(
@@ -145,7 +145,7 @@ public void testCreateFromImage256() throws IOException
145145
// assertEquals(1, image.getColorModel().getNumComponents()); TODO: PdfBox-Android
146146
Log.e("PdfBox-Android", image.getConfig().toString());
147147
PDImageXObject ximage = JPEGFactory.createFromImage(document, image);
148-
validate(ximage, 8, 344, 287, "jpg", PDDeviceGray.INSTANCE.getName());
148+
validate(ximage, 8, 344, 287, "jpg", PDDeviceRGB.INSTANCE.getName()); // TODO: PdfBox-Android
149149

150150
doWritePDF(document, ximage, testResultsDir, "jpeg256.pdf");
151151
}

library/src/androidTest/java/com/tom_roush/pdfbox/pdmodel/graphics/image/LosslessFactoryTest.java

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,22 @@
2121
import android.graphics.Canvas;
2222
import android.graphics.Color;
2323
import android.graphics.Paint;
24+
import android.os.Build;
2425

26+
import androidx.test.filters.FlakyTest;
2527
import androidx.test.platform.app.InstrumentationRegistry;
2628

2729
import java.io.File;
2830
import java.io.IOException;
2931

32+
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader;
3033
import com.tom_roush.pdfbox.android.TestResourceGenerator;
3134
import com.tom_roush.pdfbox.pdmodel.PDDocument;
3235
import com.tom_roush.pdfbox.pdmodel.PDPage;
3336
import com.tom_roush.pdfbox.pdmodel.PDPageContentStream;
3437
import com.tom_roush.pdfbox.pdmodel.graphics.color.PDDeviceGray;
3538
import com.tom_roush.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
3639
import com.tom_roush.pdfbox.rendering.PDFRenderer;
37-
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader;
3840

3941
import org.junit.Before;
4042
import org.junit.Test;
@@ -291,4 +293,59 @@ private void checkIdentRGB(Bitmap expectedImage, Bitmap actualImage)
291293
}
292294

293295
// doBitmaskTransparencyTest: Android does not have bitmask transparency
296+
297+
/**
298+
* Test lossless encoding of CMYK images
299+
*/
300+
// public void testCreateLosslessFromImageCMYK() throws IOException TODO: PdfBox-Android
301+
302+
// public void testCreateLosslessFrom16Bit() throws IOException TODO: PdfBox-Android
303+
304+
// public void testCreateLosslessFromImageINT_BGR() throws IOException TODO: PdfBox-Android
305+
306+
// public void testCreateLosslessFromImageINT_RGB() throws IOException TODO: PdfBox-Android
307+
308+
// public void testCreateLosslessFromImageBYTE_3BGR() throws IOException TODO: PdfBox-Android
309+
310+
@FlakyTest(detail = "Behavior depends heavily on API level / device")
311+
@Test
312+
public void testCreateLosslessFrom16BitPNG() throws IOException
313+
{
314+
// TODO: PdfBox-Android PNG is reduced to 8 bit, this causes changes in test values
315+
PDDocument document = new PDDocument();
316+
File TARGETDIR = new File(testContext.getCacheDir(), "imgs");
317+
TARGETDIR.mkdirs();
318+
File imgFile = TestResourceGenerator.downloadTestResource(TARGETDIR, "PDFBOX-4184-16bit.png", "https://issues.apache.org/jira/secure/attachment/12929821/16bit.png");
319+
assumeNotNull(imgFile);
320+
Bitmap image = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
321+
Bitmap compareImage;
322+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
323+
{
324+
// TODO: PdfBox-Android This is a workaround for RGBA_16 failing the checkIdent calls
325+
compareImage = image.copy(Bitmap.Config.ARGB_8888, false);
326+
}
327+
else
328+
{
329+
compareImage = image;
330+
}
331+
332+
// assertEquals(64, image.getColorModel().getPixelSize());
333+
// assertEquals(Transparency.TRANSLUCENT, image.getColorModel().getTransparency());
334+
// assertEquals(4, image.getRaster().getNumDataElements());
335+
// assertEquals(java.awt.image.DataBuffer.TYPE_USHORT, image.getRaster().getDataBuffer().getDataType());
336+
337+
PDImageXObject ximage = LosslessFactory.createFromImage(document, image);
338+
339+
int w = image.getWidth();
340+
int h = image.getHeight();
341+
validate(ximage, 8, w, h, "png", PDDeviceRGB.INSTANCE.getName());
342+
checkIdent(compareImage, ximage.getImage());
343+
checkIdentRGB(compareImage, ximage.getOpaqueImage());
344+
345+
assertNotNull(ximage.getSoftMask());
346+
validate(ximage.getSoftMask(), 8, w, h, "png", PDDeviceGray.INSTANCE.getName());
347+
// assertEquals(35, colorCount(ximage.getSoftMask().getImage())); TODO: PdfBox-Android
348+
349+
doWritePDF(document, ximage, testResultsDir, "png16bit.pdf");
350+
}
294351
}

library/src/androidTest/java/com/tom_roush/pdfbox/pdmodel/graphics/image/ValidateXImage.java

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@
2828
import com.tom_roush.pdfbox.pdmodel.PDDocument;
2929
import com.tom_roush.pdfbox.pdmodel.PDPage;
3030
import com.tom_roush.pdfbox.pdmodel.PDPageContentStream;
31+
import com.tom_roush.pdfbox.pdmodel.PDPageContentStream.AppendMode;
3132
import com.tom_roush.pdfbox.rendering.PDFRenderer;
3233

33-
import static org.junit.Assert.assertEquals;
34-
import static org.junit.Assert.assertNotNull;
35-
import static org.junit.Assert.assertTrue;
34+
import static junit.framework.TestCase.assertEquals;
35+
import static junit.framework.TestCase.assertNotNull;
36+
import static junit.framework.TestCase.assertTrue;
3637

3738
/**
3839
* Helper class to do some validations for PDImageXObject.
@@ -41,8 +42,7 @@
4142
*/
4243
public class ValidateXImage
4344
{
44-
public static void validate(PDImageXObject ximage, int bpc, int width, int height,
45-
String format, String colorSpaceName) throws IOException
45+
public static void validate(PDImageXObject ximage, int bpc, int width, int height, String format, String colorSpaceName) throws IOException
4646
{
4747
// check the dictionary
4848
assertNotNull(ximage);
@@ -55,10 +55,7 @@ public static void validate(PDImageXObject ximage, int bpc, int width, int heigh
5555
assertEquals(width, ximage.getWidth());
5656
assertEquals(height, ximage.getHeight());
5757
assertEquals(format, ximage.getSuffix());
58-
if (!format.equals("jpg")) // TODO: PdfBox-Android
59-
{
60-
assertEquals(colorSpaceName, ximage.getColorSpace().getName());
61-
}
58+
assertEquals(colorSpaceName, ximage.getColorSpace().getName());
6259

6360
// check the image
6461
assertNotNull(ximage.getImage());
@@ -93,12 +90,12 @@ static int colorCount(Bitmap bim)
9390
Set<Integer> colors = new HashSet<Integer>();
9491
int w = bim.getWidth();
9592
int h = bim.getHeight();
96-
97-
int[] bimPixels = new int[w * h];
98-
bim.getPixels(bimPixels, 0, w, 0, 0, w, h);
99-
for (int pixel : bimPixels)
93+
for (int y = 0; y < h; y++)
10094
{
101-
colors.add(pixel);
95+
for (int x = 0; x < w; x++)
96+
{
97+
colors.add(bim.getPixel(x, y));
98+
}
10299
}
103100
return colors.size();
104101
}
@@ -115,8 +112,7 @@ static void doWritePDF(PDDocument document, PDImageXObject ximage, File testResu
115112

116113
PDPage page = new PDPage();
117114
document.addPage(page);
118-
PDPageContentStream contentStream = new PDPageContentStream(document, page,
119-
PDPageContentStream.AppendMode.APPEND, false);
115+
PDPageContentStream contentStream = new PDPageContentStream(document, page, AppendMode.APPEND, false);
120116
contentStream.drawImage(ximage, 150, 300);
121117
contentStream.drawImage(ximage, 200, 350);
122118
contentStream.close();
@@ -127,7 +123,7 @@ static void doWritePDF(PDDocument document, PDImageXObject ximage, File testResu
127123
document.save(pdfFile);
128124
document.close();
129125

130-
document = PDDocument.load(pdfFile, (String) null);
126+
document = PDDocument.load(pdfFile, (String)null);
131127
assertEquals(1, count(document.getPage(0).getResources().getXObjectNames()));
132128
new PDFRenderer(document).renderImage(0);
133129
document.close();
@@ -157,21 +153,19 @@ public static void checkIdent(Bitmap expectedImage, Bitmap actualImage)
157153
int h = expectedImage.getHeight();
158154
assertEquals(w, actualImage.getWidth());
159155
assertEquals(h, actualImage.getHeight());
160-
161-
int[] expectedPixels = new int[w * h];
162-
expectedImage.getPixels(expectedPixels, 0, w, 0, 0, w, h);
163-
int[] actualPixels = new int[w * h];
164-
actualImage.getPixels(actualPixels, 0, w, 0, 0, w, h);
165156
for (int y = 0; y < h; ++y)
166157
{
167158
for (int x = 0; x < w; ++x)
168159
{
169-
if (expectedPixels[x + w * y] != actualPixels[x + w * y])
160+
if (expectedImage.getPixel(x, y) != actualImage.getPixel(x, y))
170161
{
171-
errMsg = String.format("(%d,%d) %08X != %08X", x, y, expectedPixels[x + w * y], actualPixels[x + w * y]);
162+
errMsg = String.format("(%d,%d) expected: <%08X> but was: <%08X>; ", x, y, expectedImage.getPixel(x, y), actualImage.getPixel(x, y));
172163
}
173-
assertEquals(errMsg, expectedPixels[x + w * y], actualPixels[x + w * y]);
164+
assertEquals(errMsg, expectedImage.getPixel(x, y), actualImage.getPixel(x, y));
174165
}
175166
}
176167
}
168+
169+
170+
177171
}

library/src/main/java/com/tom_roush/fontbox/ttf/CmapSubtable.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,10 @@ protected void processSubtype2(TTFDataStream data, int numGlyphs) throws IOExcep
510510
if (p > 0)
511511
{
512512
p = (p + idDelta) % 65536;
513+
if (p < 0)
514+
{
515+
p += 65536;
516+
}
513517
}
514518

515519
if (p >= numGlyphs)

library/src/main/java/com/tom_roush/fontbox/ttf/CmapTable.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@ public class CmapTable extends TTFTable
6868
* @param data The stream to read the data from.
6969
* @throws IOException If there is an error reading the data.
7070
*/
71+
@Override
7172
public void read(TrueTypeFont ttf, TTFDataStream data) throws IOException
7273
{
74+
@SuppressWarnings({"unused", "squid:S1854", "squid:S1481"})
7375
int version = data.readUnsignedShort();
7476
int numberOfTables = data.readUnsignedShort();
7577
cmaps = new CmapSubtable[numberOfTables];

library/src/main/java/com/tom_roush/fontbox/ttf/GlyphTable.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,14 @@ public void read(TrueTypeFont ttf, TTFDataStream data) throws IOException
8080

8181
/**
8282
* Returns all glyphs. This method can be very slow.
83+
*
84+
* @throws IOException If there is an error reading the data.
8385
*/
8486
public GlyphData[] getGlyphs() throws IOException
8587
{
86-
synchronized (font)
88+
// PDFBOX-4219: synchronize on data because it is accessed by several threads
89+
// when PDFBox is accessing a standard 14 font for the first time
90+
synchronized (data)
8791
{
8892
// the glyph offsets
8993
long[] offsets = loca.getOffsets();
@@ -157,7 +161,9 @@ public GlyphData getGlyph(int gid) throws IOException
157161
return glyphs[gid];
158162
}
159163

160-
synchronized (font)
164+
// PDFBOX-4219: synchronize on data because it is accessed by several threads
165+
// when PDFBox is accessing a standard 14 font for the first time
166+
synchronized (data)
161167
{
162168
// read a single glyph
163169
long[] offsets = loca.getOffsets();

library/src/main/java/com/tom_roush/fontbox/ttf/TrueTypeFont.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,17 @@ public long getOriginalDataSize()
345345
*/
346346
void readTable(TTFTable table) throws IOException
347347
{
348-
// save current position
349-
long currentPosition = data.getCurrentPosition();
350-
data.seek(table.getOffset());
351-
table.read(this, data);
352-
// restore current position
353-
data.seek(currentPosition);
348+
// PDFBOX-4219: synchronize on data because it is accessed by several threads
349+
// when PDFBox is accessing a standard 14 font for the first time
350+
synchronized (data)
351+
{
352+
// save current position
353+
long currentPosition = data.getCurrentPosition();
354+
data.seek(table.getOffset());
355+
table.read(this, data);
356+
// restore current position
357+
data.seek(currentPosition);
358+
}
354359
}
355360

356361
/**

library/src/main/java/com/tom_roush/pdfbox/contentstream/PDFStreamEngine.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public final void addOperator(OperatorProcessor op)
116116
}
117117

118118
/**
119-
* Initialises the stream engine for the given page.
119+
* Initializes the stream engine for the given page.
120120
*/
121121
private void initPage(PDPage page)
122122
{
@@ -134,7 +134,7 @@ private void initPage(PDPage page)
134134
}
135135

136136
/**
137-
* This will initialise and process the contents of the stream.
137+
* This will initialize and process the contents of the stream.
138138
*
139139
* @param page the page to process
140140
* @throws IOException if there is an error accessing the stream

0 commit comments

Comments
 (0)