Skip to content

Commit 9c895e8

Browse files
committed
Change DocumentRevisionsValidator allowedReferences checks to have info status
DEVSIX-8392
1 parent 32566bd commit 9c895e8

File tree

7 files changed

+77
-12
lines changed

7 files changed

+77
-12
lines changed

sign/src/main/java/com/itextpdf/signatures/validation/v1/DocumentRevisionsValidator.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ public class DocumentRevisionsValidator {
132132
private IMetaInfo metaInfo = new ValidationMetaInfo();
133133
private AccessPermissions accessPermissions = AccessPermissions.ANNOTATION_MODIFICATION;
134134
private AccessPermissions requestedAccessPermissions = AccessPermissions.UNSPECIFIED;
135+
private ReportItemStatus unexpectedXrefChangesStatus = ReportItemStatus.INFO;
135136
private Set<PdfObject> checkedAnnots;
136137
private Set<PdfDictionary> newlyAddedFields;
137138

@@ -169,6 +170,19 @@ public DocumentRevisionsValidator setAccessPermissions(AccessPermissions accessP
169170
return this;
170171
}
171172

173+
/**
174+
* Set the status to be used for the report items produced during docMDP validation in case revision contains
175+
* unexpected changes in the XREF table. Default value is {@link ReportItemStatus#INFO}.
176+
*
177+
* @param status {@link ReportItemStatus} to be used in case of unexpected changes in the XREF table
178+
*
179+
* @return the same {@link DocumentRevisionsValidator} instance.
180+
*/
181+
public DocumentRevisionsValidator setUnexpectedXrefChangesStatus(ReportItemStatus status) {
182+
this.unexpectedXrefChangesStatus = status;
183+
return this;
184+
}
185+
172186
/**
173187
* Validate all document revisions according to docMDP and fieldMDP transform methods.
174188
*
@@ -273,12 +287,13 @@ void validateRevision(DocumentRevision previousRevision, DocumentRevision curren
273287
if (!isMaxGenerationObject(indirectReference) &&
274288
referenceWasInPrevDocument && !referenceAllowedToBeRemoved) {
275289
validationReport.addReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.format(
276-
OBJECT_REMOVED, indirectReference.getObjNumber()), ReportItemStatus.INVALID));
290+
OBJECT_REMOVED, indirectReference.getObjNumber()), unexpectedXrefChangesStatus));
277291
}
278292
} else if (!checkAllowedReferences(currentAllowedReferences, previousAllowedReferences,
279-
indirectReference, documentWithoutRevision)) {
293+
indirectReference, documentWithoutRevision) &&
294+
!isAllowedStreamObj(indirectReference, documentWithRevision)) {
280295
validationReport.addReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.format(
281-
UNEXPECTED_ENTRY_IN_XREF, indirectReference.getObjNumber()), ReportItemStatus.INVALID));
296+
UNEXPECTED_ENTRY_IN_XREF, indirectReference.getObjNumber()), unexpectedXrefChangesStatus));
282297
}
283298
}
284299
} catch (IOException exception) {
@@ -1323,6 +1338,15 @@ private boolean checkAllowedReferences(Set<PdfIndirectReference> currentAllowedR
13231338
return false;
13241339
}
13251340

1341+
private boolean isAllowedStreamObj(PdfIndirectReference indirectReference, PdfDocument document) {
1342+
PdfObject pdfObject = document.getPdfObject(indirectReference.getObjNumber());
1343+
if (pdfObject instanceof PdfStream) {
1344+
PdfName type = ((PdfStream) pdfObject).getAsName(PdfName.Type);
1345+
return PdfName.XRef.equals(type) || PdfName.ObjStm.equals(type);
1346+
}
1347+
return false;
1348+
}
1349+
13261350
// Allowed references creation nested methods section:
13271351

13281352
private Set<PdfIndirectReference> createAllowedDssEntries(PdfDocument document) {

sign/src/test/java/com/itextpdf/signatures/validation/v1/DocumentRevisionsValidatorIntegrationTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,4 +459,43 @@ public void removeUnnamedFieldTest() throws Exception {
459459
Assert.assertEquals(AccessPermissions.ANNOTATION_MODIFICATION, validator.getAccessPermissions());
460460
}
461461
}
462+
463+
@Test
464+
public void fullCompressionModeLevel1Test() throws Exception {
465+
try (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fullCompressionModeLevel1.pdf"))) {
466+
DocumentRevisionsValidator validator = builder.buildDocumentRevisionsValidator();
467+
ValidationReport report = validator.validateAllDocumentRevisions(validationContext, document);
468+
469+
Assert.assertEquals(AccessPermissions.NO_CHANGES_PERMITTED, validator.getAccessPermissions());
470+
471+
AssertValidationReport.assertThat(report, a -> a.hasStatus(ValidationResult.VALID)
472+
.hasNumberOfFailures(0).hasNumberOfLogs(0));
473+
}
474+
}
475+
476+
@Test
477+
public void fullCompressionModeLevel2Test() throws Exception {
478+
try (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fullCompressionModeLevel2.pdf"))) {
479+
DocumentRevisionsValidator validator = builder.buildDocumentRevisionsValidator();
480+
ValidationReport report = validator.validateAllDocumentRevisions(validationContext, document);
481+
482+
Assert.assertEquals(AccessPermissions.FORM_FIELDS_MODIFICATION, validator.getAccessPermissions());
483+
484+
AssertValidationReport.assertThat(report, a -> a.hasStatus(ValidationResult.VALID)
485+
.hasNumberOfFailures(0).hasNumberOfLogs(0));
486+
}
487+
}
488+
489+
@Test
490+
public void fullCompressionModeLevel3Test() throws Exception {
491+
try (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fullCompressionModeLevel3.pdf"))) {
492+
DocumentRevisionsValidator validator = builder.buildDocumentRevisionsValidator();
493+
ValidationReport report = validator.validateAllDocumentRevisions(validationContext, document);
494+
495+
Assert.assertEquals(AccessPermissions.ANNOTATION_MODIFICATION, validator.getAccessPermissions());
496+
497+
AssertValidationReport.assertThat(report, a -> a.hasStatus(ValidationResult.VALID)
498+
.hasNumberOfFailures(0).hasNumberOfLogs(0));
499+
}
500+
}
462501
}

sign/src/test/java/com/itextpdf/signatures/validation/v1/DocumentRevisionsValidatorTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ public void multipleRevisionsDocumentLevel1Test() throws IOException {
9898

9999
// Between these two revisions DSS and timestamp are added, which is allowed,
100100
// but there is unused entry in the xref table, which is an itext signature generation artifact.
101-
AssertValidationReport.assertThat(validationReport, a -> a.hasStatus(ValidationResult.INVALID)
102-
.hasNumberOfFailures(1).hasNumberOfLogs(1)
101+
AssertValidationReport.assertThat(validationReport, a -> a.hasStatus(ValidationResult.VALID)
102+
.hasNumberOfFailures(0).hasNumberOfLogs(1)
103103
.hasLogItem(l -> l.withCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK)
104104
.withMessage(DocumentRevisionsValidator.UNEXPECTED_ENTRY_IN_XREF, i -> 27)
105-
.withStatus(ReportItemStatus.INVALID)));
105+
.withStatus(ReportItemStatus.INFO)));
106106

107107
validationReport = new ValidationReport();
108108
validator.validateRevision(documentRevisions.get(1), documentRevisions.get(2), document, validationReport, validationContext);
@@ -257,8 +257,9 @@ public void randomEntryAddedTest() throws IOException {
257257
@Test
258258
public void randomEntryWithoutUsageTest() throws IOException {
259259
try (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "randomEntryWithoutUsage.pdf"))) {
260-
DocumentRevisionsValidator validator = builder.buildDocumentRevisionsValidator();
261-
validator.setAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED);
260+
DocumentRevisionsValidator validator = builder.buildDocumentRevisionsValidator()
261+
.setAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED)
262+
.setUnexpectedXrefChangesStatus(ReportItemStatus.INVALID);
262263
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.getReader());
263264
List<DocumentRevision> documentRevisions = revisionsReader.getAllRevisions();
264265

sign/src/test/java/com/itextpdf/signatures/validation/v1/SignatureValidatorIntegrationTest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,19 +259,20 @@ public void validateMultipleSignaturesUsingLastKnownPoETest() throws Exception {
259259
.withRevocationDataValidator(new MockRevocationDataValidator()).buildSignatureValidator();
260260
ValidationReport report = signatureValidator.validateSignatures(document);
261261

262-
// Document contains invalid unused entry which is invalid according to DocumentRevisionsValidator.
263262
AssertValidationReport.assertThat(report, r -> r
264-
.hasStatus(ValidationResult.INVALID)
265-
.hasNumberOfLogs(5).hasNumberOfFailures(1)
263+
.hasStatus(ValidationResult.VALID)
264+
.hasNumberOfLogs(5).hasNumberOfFailures(0)
266265
.hasLogItem(l -> l
267266
.withCheckName(SignatureValidator.SIGNATURE_VERIFICATION)
268267
.withMessage(SignatureValidator.VALIDATING_SIGNATURE_NAME, p -> "timestampSig1"))
269268
.hasLogItem(l -> l
270269
.withCheckName(SignatureValidator.SIGNATURE_VERIFICATION)
271270
.withMessage(SignatureValidator.VALIDATING_SIGNATURE_NAME, p -> "Signature1"))
271+
// Document contains unused unexpected entry.
272272
.hasLogItem(l -> l
273273
.withCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK)
274-
.withMessage(DocumentRevisionsValidator.UNEXPECTED_ENTRY_IN_XREF, p -> "28"))
274+
.withMessage(DocumentRevisionsValidator.UNEXPECTED_ENTRY_IN_XREF, p -> "28")
275+
.withStatus(ReportItem.ReportItemStatus.INFO))
275276
);
276277
}
277278
}

0 commit comments

Comments
 (0)