Skip to content

Commit 0178a9f

Browse files
Yahor MartsynkovskyiText-CI
authored andcommitted
Fix constructor of PdfReader to close() the PdfTokenizer when exception thrown
Add PdfWriter/PdfReader/PdfDocument constructors to try-with-resources Add tests to compareLinkAnnotation method and encrypt method DEVSIX-3504
1 parent 8a77dd3 commit 0178a9f

File tree

8 files changed

+343
-175
lines changed

8 files changed

+343
-175
lines changed

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfEncryptor.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ This file is part of the iText (R) project.
4343
*/
4444
package com.itextpdf.kernel.pdf;
4545

46+
import java.io.IOException;
4647
import java.io.OutputStream;
4748
import java.security.PrivateKey;
4849
import java.util.Map;
@@ -241,12 +242,15 @@ public PdfEncryptor setEncryptionProperties(EncryptionProperties properties) {
241242
public void encrypt(PdfReader reader, OutputStream os, Map<String, String> newInfo) {
242243
WriterProperties writerProperties = new WriterProperties();
243244
writerProperties.encryptionProperties = properties;
244-
PdfWriter writer = new PdfWriter(os, writerProperties);
245245
StampingProperties stampingProperties = new StampingProperties();
246246
stampingProperties.setEventCountingMetaInfo(metaInfo);
247-
PdfDocument document = new PdfDocument(reader, writer, stampingProperties);
248-
document.getDocumentInfo().setMoreInfo(newInfo);
249-
document.close();
247+
try (PdfWriter writer = new PdfWriter(os, writerProperties);
248+
PdfDocument document = new PdfDocument(reader, writer, stampingProperties)) {
249+
document.getDocumentInfo().setMoreInfo(newInfo);
250+
} catch (IOException e) {
251+
//The close() method of OutputStream throws an exception, but we don't need to do anything in this case,
252+
// because OutputStream#close() does nothing.
253+
}
250254
}
251255

252256
/**

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfReader.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1312,8 +1312,19 @@ private void readDecryptObj() {
13121312
* @throws IOException if there is a problem reading the byte source
13131313
*/
13141314
private static PdfTokenizer getOffsetTokeniser(IRandomAccessSource byteSource) throws IOException {
1315+
com.itextpdf.io.IOException possibleException = null;
13151316
PdfTokenizer tok = new PdfTokenizer(new RandomAccessFileOrArray(byteSource));
1316-
int offset = tok.getHeaderOffset();
1317+
int offset;
1318+
try {
1319+
offset = tok.getHeaderOffset();
1320+
} catch (com.itextpdf.io.IOException ex) {
1321+
possibleException = ex;
1322+
throw possibleException;
1323+
} finally {
1324+
if (possibleException != null) {
1325+
tok.close();
1326+
}
1327+
}
13171328
if (offset != 0) {
13181329
IRandomAccessSource offsetSource = new WindowRandomAccessSource(byteSource, offset);
13191330
tok = new PdfTokenizer(new RandomAccessFileOrArray(offsetSource));

kernel/src/main/java/com/itextpdf/kernel/utils/CompareTool.java

Lines changed: 124 additions & 135 deletions
Large diffs are not rendered by default.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2021 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License version 3
8+
as published by the Free Software Foundation with the addition of the
9+
following permission added to Section 15 as permitted in Section 7(a):
10+
FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
11+
ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
12+
OF THIRD PARTY RIGHTS
13+
14+
This program is distributed in the hope that it will be useful, but
15+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+
or FITNESS FOR A PARTICULAR PURPOSE.
17+
See the GNU Affero General Public License for more details.
18+
You should have received a copy of the GNU Affero General Public License
19+
along with this program; if not, see http://www.gnu.org/licenses or write to
20+
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21+
Boston, MA, 02110-1301 USA, or download the license from the following URL:
22+
http://itextpdf.com/terms-of-use/
23+
24+
The interactive user interfaces in modified source and object code versions
25+
of this program must display Appropriate Legal Notices, as required under
26+
Section 5 of the GNU Affero General Public License.
27+
28+
In accordance with Section 7(b) of the GNU Affero General Public License,
29+
a covered work must retain the producer line in every PDF that is created
30+
or manipulated using iText.
31+
32+
You can be released from the requirements of the license by purchasing
33+
a commercial license. Buying such a license is mandatory as soon as you
34+
develop commercial activities involving the iText software without
35+
disclosing the source code of your own applications.
36+
These activities include: offering paid services to customers as an ASP,
37+
serving PDFs on the fly in a web application, shipping iText with a closed
38+
source product.
39+
40+
For more information, please contact iText Software Corp. at this
41+
42+
*/
43+
package com.itextpdf.kernel.pdf;
44+
45+
import com.itextpdf.test.ExtendedITextTest;
46+
import com.itextpdf.test.annotations.type.IntegrationTest;
47+
48+
import java.io.FileOutputStream;
49+
import java.io.IOException;
50+
import org.junit.Assert;
51+
import org.junit.BeforeClass;
52+
import org.junit.Rule;
53+
import org.junit.Test;
54+
import org.junit.experimental.categories.Category;
55+
import org.junit.rules.ExpectedException;
56+
57+
@Category(IntegrationTest.class)
58+
public class PdfEncryptorTest extends ExtendedITextTest {
59+
60+
public static final String SOURCE_FOLDER = "./src/test/resources/com/itextpdf/kernel/pdf/PdfEncryptorTest/";
61+
public static final String DESTINATION_FOLDER = "./target/test/com/itextpdf/kernel/pdf/PdfEncryptorTest/";
62+
63+
64+
@BeforeClass
65+
public static void beforeClass() {
66+
createDestinationFolder(DESTINATION_FOLDER);
67+
}
68+
69+
@Test
70+
public void encryptFileTest() throws IOException {
71+
String outFileName = DESTINATION_FOLDER + "encryptFileTest.pdf";
72+
String initialFileName = SOURCE_FOLDER + "initial.pdf";
73+
PdfEncryptor encryptor = new PdfEncryptor();
74+
EncryptionProperties encryptionProperties = new EncryptionProperties();
75+
encryptionProperties.setStandardEncryption(new byte[16], new byte[16], 0, 0);
76+
encryptor.setEncryptionProperties(encryptionProperties);
77+
78+
try (PdfReader initialFile = new PdfReader(initialFileName);
79+
FileOutputStream outputStream = new FileOutputStream(outFileName)) {
80+
encryptor.encrypt(initialFile, outputStream);
81+
}
82+
83+
ReaderProperties readerProperties = new ReaderProperties();
84+
readerProperties.setPassword(new byte[16]);
85+
PdfReader outFile = new PdfReader(outFileName, readerProperties);
86+
PdfDocument doc = new PdfDocument(outFile);
87+
doc.close();
88+
Assert.assertTrue(outFile.isEncrypted());
89+
}
90+
}

kernel/src/test/java/com/itextpdf/kernel/utils/CompareToolTest.java

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,26 @@ This file is part of the iText (R) project.
4343
package com.itextpdf.kernel.utils;
4444

4545
import com.itextpdf.io.IoExceptionMessage;
46+
import com.itextpdf.io.font.constants.StandardFonts;
4647
import com.itextpdf.io.util.GhostscriptHelper;
4748
import com.itextpdf.io.util.SystemUtil;
49+
import com.itextpdf.kernel.font.PdfFontFactory;
50+
import com.itextpdf.kernel.geom.Rectangle;
51+
import com.itextpdf.kernel.pdf.PdfArray;
52+
import com.itextpdf.kernel.pdf.PdfDocument;
53+
import com.itextpdf.kernel.pdf.PdfPage;
54+
import com.itextpdf.kernel.pdf.PdfWriter;
55+
import com.itextpdf.kernel.pdf.annot.PdfLinkAnnotation;
56+
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
57+
import com.itextpdf.kernel.pdf.navigation.PdfExplicitDestination;
4858
import com.itextpdf.test.ExtendedITextTest;
4959
import com.itextpdf.test.annotations.LogMessage;
5060
import com.itextpdf.test.annotations.LogMessages;
5161
import com.itextpdf.test.annotations.type.IntegrationTest;
5262

5363
import java.io.File;
64+
import java.io.IOException;
65+
import javax.xml.parsers.ParserConfigurationException;
5466
import org.junit.Assert;
5567
import org.junit.BeforeClass;
5668
import org.junit.Rule;
@@ -59,9 +71,6 @@ This file is part of the iText (R) project.
5971
import org.junit.rules.ExpectedException;
6072
import org.xml.sax.SAXException;
6173

62-
import javax.xml.parsers.ParserConfigurationException;
63-
import java.io.IOException;
64-
6574
@Category(IntegrationTest.class)
6675
public class CompareToolTest extends ExtendedITextTest {
6776

@@ -218,4 +227,66 @@ public void compareVisuallyDiffTestTest() throws IOException, InterruptedExcepti
218227
Assert.assertTrue(new File(destinationFolder + "diff_1.png").exists());
219228
Assert.assertTrue(new File(destinationFolder + "diff_2.png").exists());
220229
}
230+
231+
@Test
232+
public void compareDiffFilesWithSameLinkAnnotationTest() throws IOException {
233+
String firstPdf = destinationFolder + "firstPdf.pdf";
234+
String secondPdf = destinationFolder + "secondPdf.pdf";
235+
PdfDocument firstDocument = new PdfDocument(new PdfWriter(firstPdf));
236+
237+
PdfPage page1FirstDocument = firstDocument.addNewPage();
238+
PdfCanvas canvas = new PdfCanvas(page1FirstDocument);
239+
canvas.beginText();
240+
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER_BOLD), 14);
241+
canvas.moveText(100, 600);
242+
canvas.showText("Page 1");
243+
canvas.moveText(0, -30);
244+
canvas.showText("Link to page 1. Click here!");
245+
canvas.endText();
246+
canvas.release();
247+
page1FirstDocument.addAnnotation(new PdfLinkAnnotation(new Rectangle(100, 560, 260, 25)).setDestination(
248+
PdfExplicitDestination.createFit(page1FirstDocument)).setBorder(new PdfArray(new float[] {0, 0, 1})));
249+
page1FirstDocument.flush();
250+
firstDocument.close();
251+
252+
PdfDocument secondDocument = new PdfDocument(new PdfWriter(secondPdf));
253+
PdfPage page1secondDocument = secondDocument.addNewPage();
254+
canvas = new PdfCanvas(page1secondDocument);
255+
canvas.beginText();
256+
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER_BOLD), 14);
257+
canvas.moveText(100, 600);
258+
canvas.showText("Page 1 wit different Text");
259+
canvas.moveText(0, -30);
260+
canvas.showText("Link to page 1. Click here!");
261+
canvas.endText();
262+
canvas.release();
263+
page1secondDocument.addAnnotation(new PdfLinkAnnotation(new Rectangle(100, 560, 260, 25)).setDestination(
264+
PdfExplicitDestination.createFit(page1secondDocument)).setBorder(new PdfArray(new float[] {0, 0, 1})));
265+
page1secondDocument.flush();
266+
secondDocument.close();
267+
268+
Assert.assertNull(new CompareTool().compareLinkAnnotations(firstPdf, secondPdf));
269+
}
270+
271+
@Test
272+
public void compareFilesWithDiffLinkAnnotationTest() throws IOException {
273+
String firstPdf = destinationFolder + "outPdf.pdf";
274+
String secondPdf = destinationFolder + "secondPdf.pdf";
275+
PdfDocument firstDocument = new PdfDocument(new PdfWriter(firstPdf));
276+
PdfDocument secondDocument = new PdfDocument(new PdfWriter(secondPdf));
277+
278+
PdfPage page1FirstDocument = firstDocument.addNewPage();
279+
page1FirstDocument.addAnnotation(new PdfLinkAnnotation(new Rectangle(100, 560, 400, 50)).setDestination(
280+
PdfExplicitDestination.createFit(page1FirstDocument)).setBorder(new PdfArray(new float[] {0, 0, 1})));
281+
page1FirstDocument.flush();
282+
firstDocument.close();
283+
284+
PdfPage page1SecondDocument = secondDocument.addNewPage();
285+
page1SecondDocument.addAnnotation(new PdfLinkAnnotation(new Rectangle(100, 560, 260, 25)).setDestination(
286+
PdfExplicitDestination.createFit(page1SecondDocument)).setBorder(new PdfArray(new float[] {0, 0, 1})));
287+
page1SecondDocument.flush();
288+
secondDocument.close();
289+
290+
Assert.assertNotNull(new CompareTool().compareLinkAnnotations(firstPdf, secondPdf));
291+
}
221292
}
Binary file not shown.

sign/src/main/java/com/itextpdf/signatures/LtvVerifier.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,13 +292,15 @@ public void switchToPreviousRevision() throws IOException, GeneralSecurityExcept
292292
List<String> names = sgnUtil.getSignatureNames();
293293
if (names.size() > 1) {
294294
signatureName = names.get(names.size() - 2);
295-
document = new PdfDocument(new PdfReader(sgnUtil.extractRevision(signatureName)), new DocumentProperties().setEventCountingMetaInfo(metaInfo));
295+
try (PdfReader readerTmp = new PdfReader(sgnUtil.extractRevision(signatureName))) {
296+
document = new PdfDocument(readerTmp, new DocumentProperties().setEventCountingMetaInfo(metaInfo));
296297
this.acroForm = PdfAcroForm.getAcroForm(document, true);
297298
this.sgnUtil = new SignatureUtil(document);
298299
names = sgnUtil.getSignatureNames();
299300
signatureName = names.get(names.size() - 1);
300301
pkcs7 = coversWholeDocument();
301302
LOGGER.info(MessageFormatUtil.format("Checking {0}signature {1}", pkcs7.isTsp() ? "document-level timestamp " : "", signatureName));
303+
}
302304
}
303305
else {
304306
LOGGER.info("No signatures in revision");

svg/src/main/java/com/itextpdf/svg/converter/SvgConverter.java

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -546,39 +546,40 @@ public static void createPdf(InputStream svgStream, OutputStream pdfDest, ISvgCo
546546
if (writerProps == null) {
547547
writerProps = new WriterProperties();
548548
}
549-
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(pdfDest, writerProps));
550-
// Process
551-
ISvgProcessorResult processorResult = process(parse(svgStream, props), props);
549+
try (PdfWriter writer = new PdfWriter(pdfDest, writerProps);
550+
PdfDocument pdfDocument = new PdfDocument(writer)) {
551+
// Process
552+
ISvgProcessorResult processorResult = process(parse(svgStream, props), props);
553+
554+
ResourceResolver resourceResolver = SvgConverter.getResourceResolver(processorResult, props);
555+
SvgDrawContext drawContext = new SvgDrawContext(resourceResolver, processorResult.getFontProvider());
556+
if (processorResult instanceof SvgProcessorResult) {
557+
drawContext.setCssContext(((SvgProcessorResult) processorResult).getContext().getCssContext());
558+
}
552559

553-
ResourceResolver resourceResolver = SvgConverter.getResourceResolver(processorResult, props);
554-
SvgDrawContext drawContext = new SvgDrawContext(resourceResolver, processorResult.getFontProvider());
555-
if (processorResult instanceof SvgProcessorResult) {
556-
drawContext.setCssContext(((SvgProcessorResult) processorResult).getContext().getCssContext());
560+
drawContext.addNamedObjects(processorResult.getNamedObjects());
561+
// Add temp fonts
562+
drawContext.setTempFonts(processorResult.getTempFonts());
563+
564+
ISvgNodeRenderer topSvgRenderer = processorResult.getRootRenderer();
565+
// Extract topmost dimensions
566+
checkNull(topSvgRenderer);
567+
checkNull(pdfDocument);
568+
float width, height;
569+
570+
float[] wh = extractWidthAndHeight(topSvgRenderer);
571+
width = wh[0];
572+
height = wh[1];
573+
574+
// Adjust pagesize and create new page
575+
pdfDocument.setDefaultPageSize(new PageSize(width, height));
576+
PdfPage page = pdfDocument.addNewPage();
577+
PdfCanvas pageCanvas = new PdfCanvas(page);
578+
// Add to the first page
579+
PdfFormXObject xObject = convertToXObject(topSvgRenderer, pdfDocument, drawContext);
580+
// Draw
581+
draw(xObject, pageCanvas);
557582
}
558-
559-
drawContext.addNamedObjects(processorResult.getNamedObjects());
560-
// Add temp fonts
561-
drawContext.setTempFonts(processorResult.getTempFonts());
562-
563-
ISvgNodeRenderer topSvgRenderer = processorResult.getRootRenderer();
564-
// Extract topmost dimensions
565-
checkNull(topSvgRenderer);
566-
checkNull(pdfDocument);
567-
float width, height;
568-
569-
float[] wh = extractWidthAndHeight(topSvgRenderer);
570-
width = wh[0];
571-
height = wh[1];
572-
573-
// Adjust pagesize and create new page
574-
pdfDocument.setDefaultPageSize(new PageSize(width, height));
575-
PdfPage page = pdfDocument.addNewPage();
576-
PdfCanvas pageCanvas = new PdfCanvas(page);
577-
// Add to the first page
578-
PdfFormXObject xObject = convertToXObject(topSvgRenderer, pdfDocument, drawContext);
579-
// Draw
580-
draw(xObject, pageCanvas);
581-
pdfDocument.close();
582583
}
583584

584585
/**

0 commit comments

Comments
 (0)