Skip to content

Commit ce35dbc

Browse files
author
Eugene Bochilo
committed
Fix DocumentRevisionsValidator producing false negative result because of Tabs entry modification
DEVSIX-8818
1 parent 8d4fbb6 commit ce35dbc

File tree

5 files changed

+55
-0
lines changed

5 files changed

+55
-0
lines changed

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ public class DocumentRevisionsValidator {
117117
static final String PAGES_MODIFIED = "Pages structure was unexpectedly modified.";
118118
static final String PAGE_ANNOTATIONS_MODIFIED = "Page annotations were unexpectedly modified.";
119119
static final String PAGE_MODIFIED = "Page was unexpectedly modified.";
120+
static final String TABS_MODIFIED = "Tabs entry in a page dictionary was unexpectedly modified.";
120121
static final String PERMISSIONS_REMOVED = "Permissions dictionary was removed from the catalog.";
121122
static final String PERMISSIONS_TYPE = "Permissions must be a dictionary.";
122123
static final String PERMISSION_REMOVED = "Permission \"{0}\" dictionary was removed or unexpectedly modified.";
@@ -1310,17 +1311,24 @@ private boolean comparePages(PdfDictionary prevPages, PdfDictionary currPages, V
13101311
previousPageCopy.remove(PdfName.Annots);
13111312
previousPageCopy.remove(PdfName.Parent);
13121313
previousPageCopy.remove(PdfName.StructParents);
1314+
previousPageCopy.remove(PdfName.Tabs);
13131315
PdfDictionary currentPageCopy = new PdfDictionary(currentKid);
13141316
currentPageCopy.remove(PdfName.Annots);
13151317
currentPageCopy.remove(PdfName.Parent);
13161318
currentPageCopy.remove(PdfName.StructParents);
1319+
currentPageCopy.remove(PdfName.Tabs);
13171320
if (!comparePdfObjects(previousPageCopy, currentPageCopy, usuallyModifiedObjects) ||
13181321
!compareIndirectReferencesObjNums(previousKid.get(PdfName.Parent),
13191322
currentKid.get(PdfName.Parent), report, "Page parent")) {
13201323
report.addReportItem(new ReportItem(DOC_MDP_CHECK, PAGE_MODIFIED, ReportItemStatus.INVALID));
13211324
return false;
13221325
}
13231326

1327+
if (!compareTabs(previousKid.getAsName(PdfName.Tabs), currentKid.getAsName(PdfName.Tabs))) {
1328+
report.addReportItem(new ReportItem(DOC_MDP_CHECK, TABS_MODIFIED, ReportItemStatus.INVALID));
1329+
return false;
1330+
}
1331+
13241332
PdfArray prevNotModifiableAnnots = getAnnotsNotAllowedToBeModified(previousKid);
13251333
PdfArray currNotModifiableAnnots = getAnnotsNotAllowedToBeModified(currentKid);
13261334
if (!comparePageAnnotations(prevNotModifiableAnnots, currNotModifiableAnnots, report)) {
@@ -1335,6 +1343,13 @@ private boolean comparePages(PdfDictionary prevPages, PdfDictionary currPages, V
13351343
return true;
13361344
}
13371345

1346+
private boolean compareTabs(PdfName previousTabs, PdfName currentTabs) {
1347+
if (getAccessPermissions() == AccessPermissions.ANNOTATION_MODIFICATION) {
1348+
return true;
1349+
}
1350+
return Objects.equals(previousTabs, currentTabs) || (previousTabs == null && currentTabs.equals(PdfName.S));
1351+
}
1352+
13381353
private void collectRemovedAndAddedAnnotations(PdfArray previousAnnotations, PdfArray currentAnnotations) {
13391354
ValidationReport dummyReport = new ValidationReport();
13401355
List<PdfDictionary> prevAnnots = new ArrayList<>();

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,46 @@ public void taggedDocRemoveStructTreeElementTest(boolean continueValidationAfter
550550
}
551551
}
552552

553+
@ParameterizedTest(name = "Continue validation after failure: {0}")
554+
@MethodSource("createParameters")
555+
public void annotationModificationAllowedTabsChangesTest(boolean continueValidationAfterFail) throws IOException {
556+
setUp(continueValidationAfterFail);
557+
try (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "annotationModificationAllowedTabsChangesTest.pdf"))) {
558+
DocumentRevisionsValidator validator = builder.buildDocumentRevisionsValidator();
559+
ValidationReport report = validator.validateAllDocumentRevisions(validationContext, document);
560+
561+
AssertValidationReport.assertThat(report, a -> a.hasStatus(ValidationResult.VALID).hasNumberOfLogs(0));
562+
}
563+
}
564+
565+
@ParameterizedTest(name = "Continue validation after failure: {0}")
566+
@MethodSource("createParameters")
567+
public void annotationModificationNotAllowedTabsChangesTest(boolean continueValidationAfterFail) throws IOException {
568+
setUp(continueValidationAfterFail);
569+
try (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "annotationModificationNotAllowedTabsChangesTest.pdf"))) {
570+
DocumentRevisionsValidator validator = builder.buildDocumentRevisionsValidator();
571+
ValidationReport report = validator.validateAllDocumentRevisions(validationContext, document);
572+
573+
AssertValidationReport.assertThat(report, a -> a.hasStatus(ValidationResult.INVALID)
574+
.hasNumberOfFailures(1)
575+
.hasLogItem(l -> l.withCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK)
576+
.withMessage(DocumentRevisionsValidator.TABS_MODIFIED)
577+
.withStatus(ReportItemStatus.INVALID)));
578+
}
579+
}
580+
581+
@ParameterizedTest(name = "Continue validation after failure: {0}")
582+
@MethodSource("createParameters")
583+
public void annotationModificationNotAllowedTabsSetToDefaultTest(boolean continueValidationAfterFail) throws IOException {
584+
setUp(continueValidationAfterFail);
585+
try (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "annotationModificationNotAllowedTabsSetToDefaultTest.pdf"))) {
586+
DocumentRevisionsValidator validator = builder.buildDocumentRevisionsValidator();
587+
ValidationReport report = validator.validateAllDocumentRevisions(validationContext, document);
588+
589+
AssertValidationReport.assertThat(report, a -> a.hasStatus(ValidationResult.VALID).hasNumberOfLogs(0));
590+
}
591+
}
592+
553593
@ParameterizedTest(name = "Continue validation after failure: {0}")
554594
@MethodSource("createParameters")
555595
public void outlinesNotModifiedTest(boolean continueValidationAfterFail) throws IOException {

0 commit comments

Comments
 (0)