Skip to content

Commit

Permalink
FOP-3215: Allow object-streams with signing and encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
simonsteiner1984 committed Oct 29, 2024
1 parent c756924 commit 1e2c135
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 22 deletions.
3 changes: 0 additions & 3 deletions fop-core/src/main/java/org/apache/fop/pdf/PDFDocument.java
Original file line number Diff line number Diff line change
Expand Up @@ -1202,9 +1202,6 @@ private boolean useObjectStreams() {
if (objectStreamsEnabled && linearizationEnabled) {
throw new UnsupportedOperationException("Linearization and use-object-streams can't be both enabled");
}
if (objectStreamsEnabled && isEncryptionActive()) {
throw new UnsupportedOperationException("Encryption and use-object-streams can't be both enabled");
}
return objectStreamsEnabled || (accessibilityEnabled
&& versionController.getPDFVersion().compareTo(Version.V1_5) >= 0 && !isLinearizationEnabled());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -837,4 +837,7 @@ public Version getPDFVersion() {
return pdfVersion;
}

public boolean supportsObjectStream() {
return false;
}
}
4 changes: 4 additions & 0 deletions fop-core/src/main/java/org/apache/fop/pdf/PDFRoot.java
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,8 @@ public void addAF(PDFFileSpec fileSpec) {
af.add(fileSpec);
fileSpec.put("AFRelationship", new PDFName("Data"));
}

public boolean supportsObjectStream() {
return !getDocument().isEncryptionActive();
}
}
6 changes: 5 additions & 1 deletion fop-core/src/main/java/org/apache/fop/pdf/PDFSignature.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ public int output(OutputStream stream) throws IOException {
startOfDocMDP = countingOutputStream.getByteCount();
return super.output(stream);
}
throw new IOException("Disable pdf linearization and use-object-streams");
throw new IOException("Disable pdf linearization");
}

public boolean supportsObjectStream() {
return false;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,22 @@
public class PDFObjectStreamTestCase {
@Test
public void testObjectStreamsEnabled() throws IOException {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
PDFDocument doc = new PDFDocument("");
String out = buildObjectStreamsPDF(doc);
Assert.assertTrue(out.contains("<<\n /Type /ObjStm\n /N 3\n /First 15\n /Length 260\n>>\n"
+ "stream\n8 0\n9 52\n4 121\n<<\n/Producer"));
}

@Test
public void testObjectStreamsWithEncryption() throws IOException {
PDFDocument doc = new PDFDocument("");
doc.setEncryption(new PDFEncryptionParams());
String out = buildObjectStreamsPDF(doc);
Assert.assertTrue(out.contains("<<\n /Type /ObjStm\n /N 3\n /First 16\n /Length 282\n>>\nstream"));
}

private String buildObjectStreamsPDF(PDFDocument doc) throws IOException {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Map<String, List<String>> filterMap = new HashMap<>();
List<String> filterList = new ArrayList<>();
filterList.add("null");
Expand All @@ -55,7 +69,6 @@ public void testObjectStreamsEnabled() throws IOException {
gen.flushPDFDoc();
doc.outputTrailer(out);
Assert.assertTrue(out.toString().contains("/Subtype /Image"));
Assert.assertTrue(out.toString().contains("<<\n /Type /ObjStm\n /N 3\n /First 15\n /Length 260\n>>\n"
+ "stream\n8 0\n9 52\n4 121\n<<\n/Producer"));
return out.toString();
}
}
46 changes: 31 additions & 15 deletions fop-core/src/test/java/org/apache/fop/pdf/PDFSigningTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,28 @@

public class PDFSigningTestCase {
@Test
public void textFO() throws Exception {
public void testFO() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
foToOutput(out, MimeConstants.MIME_PDF);
foToOutput(out, false);
String endStr = checkOutput(out);
Assert.assertTrue(endStr.contains("/FT /Sig\n"
+ " /Type /Annot\n"
+ " /Subtype /Widget\n"
+ " /F 132\n"
+ " /T (Signature1)\n"
+ " /TU (Signature1)\n"
+ " /Rect [0 0 0 0]"));
}

@Test
public void testWithObjectStreams() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
foToOutput(out, true);
String endStr = checkOutput(out);
Assert.assertFalse(endStr.contains("/Subtype /Widget"));
}

private String checkOutput(ByteArrayOutputStream out) throws Exception {
StringTokenizer byteRange = new StringTokenizer(out.toString().split("/ByteRange ")[1]);
byteRange.nextToken();
int startOfContents = Integer.parseInt(byteRange.nextToken());
Expand All @@ -62,31 +81,28 @@ public void textFO() throws Exception {
String endStr = new String(end);
Assert.assertTrue(endStr.contains(
"/ByteRange [0 " + startOfContents + " " + endOfContents + " " + sizeOfEnd + "]"));
Assert.assertTrue(endStr.contains("/FT /Sig\n"
+ " /Type /Annot\n"
+ " /Subtype /Widget\n"
+ " /F 132\n"
+ " /T (Signature1)\n"
+ " /TU (Signature1)\n"
+ " /Rect [0 0 0 0]"));
return endStr;
}

private void foToOutput(ByteArrayOutputStream out, String mimeFopIf) throws Exception {
FopFactory fopFactory = getFopFactory();
private void foToOutput(ByteArrayOutputStream out, boolean objectStreams) throws Exception {
FopFactory fopFactory = getFopFactory(objectStreams);
FOUserAgent userAgent = fopFactory.newFOUserAgent();
Fop fop = fopFactory.newFop(mimeFopIf, userAgent, out);
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Source src = new StreamSource(LayoutMasterSetTestCase.class.getResourceAsStream("side-regions.fo"));
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
}

private FopFactory getFopFactory() throws Exception {
private FopFactory getFopFactory(boolean objectStreams) throws Exception {
String pkcs = PDFSigningTestCase.class.getResource("keystore.pkcs12").toString();
String fopxconf = "<fop version=\"1.0\">\n"
+ " <renderers>\n"
+ " <renderer mime=\"application/pdf\">\n"
+ " <sign-params>\n"
+ " <renderer mime=\"application/pdf\">\n";
if (objectStreams) {
fopxconf += "<use-object-streams>true</use-object-streams>";
}
fopxconf += " <sign-params>\n"
+ " <keystore>" + pkcs + "</keystore>\n"
+ " </sign-params>\n"
+ " </renderer>\n"
Expand Down

0 comments on commit 1e2c135

Please sign in to comment.