diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/MemoryLimitsAwareHandlerTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/MemoryLimitsAwareHandlerTest.cs index 239d7344f5..3b7be43665 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/MemoryLimitsAwareHandlerTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/MemoryLimitsAwareHandlerTest.cs @@ -22,7 +22,9 @@ You should have received a copy of the GNU Affero General Public License */ using System; using iText.Kernel.Exceptions; +using iText.Kernel.Logs; using iText.Test; +using iText.Test.Attributes; namespace iText.Kernel.Pdf { [NUnit.Framework.Category("UnitTest")] @@ -46,15 +48,15 @@ public virtual void CustomMemoryHandler() { [NUnit.Framework.Test] public virtual void OverridenMemoryHandler() { MemoryLimitsAwareHandler defaultHandler = new MemoryLimitsAwareHandler(); - MemoryLimitsAwareHandler customHandler = new _MemoryLimitsAwareHandler_58(); + MemoryLimitsAwareHandler customHandler = new _MemoryLimitsAwareHandler_64(); PdfArray filters = new PdfArray(); filters.Add(PdfName.FlateDecode); NUnit.Framework.Assert.IsFalse(defaultHandler.IsMemoryLimitsAwarenessRequiredOnDecompression(filters)); NUnit.Framework.Assert.IsTrue(customHandler.IsMemoryLimitsAwarenessRequiredOnDecompression(filters)); } - private sealed class _MemoryLimitsAwareHandler_58 : MemoryLimitsAwareHandler { - public _MemoryLimitsAwareHandler_58() { + private sealed class _MemoryLimitsAwareHandler_64 : MemoryLimitsAwareHandler { + public _MemoryLimitsAwareHandler_64() { } public override bool IsMemoryLimitsAwarenessRequiredOnDecompression(PdfArray filters) { @@ -144,6 +146,54 @@ public virtual void CheckCapacityTest() { )); } + [NUnit.Framework.Test] + [LogMessage(KernelLogMessageConstant.MEMORYLIMITAWAREHANDLER_OVERRIDE_CREATENEWINSTANCE_METHOD)] + public virtual void CreateCopyMemoryHandlerWarningTest() { + MemoryLimitsAwareHandler customHandler = new _MemoryLimitsAwareHandler_173(); + customHandler.SetMaxNumberOfElementsInXrefStructure(1); + customHandler.SetMaxXObjectsSizePerPage(2); + customHandler.SetMaxSizeOfDecompressedPdfStreamsSum(3); + customHandler.SetMaxSizeOfSingleDecompressedPdfStream(4); + MemoryLimitsAwareHandler copy = customHandler.CreateNewInstance(); + NUnit.Framework.Assert.AreEqual(1, copy.GetMaxNumberOfElementsInXrefStructure()); + NUnit.Framework.Assert.AreEqual(2, copy.GetMaxXObjectsSizePerPage()); + NUnit.Framework.Assert.AreEqual(3, copy.GetMaxSizeOfDecompressedPdfStreamsSum()); + NUnit.Framework.Assert.AreEqual(4, copy.GetMaxSizeOfSingleDecompressedPdfStream()); + } + + private sealed class _MemoryLimitsAwareHandler_173 : MemoryLimitsAwareHandler { + public _MemoryLimitsAwareHandler_173() { + } + } + + [NUnit.Framework.Test] + public virtual void CreateCopyMemoryHandlerNoWarningTest() { + MemoryLimitsAwareHandler customHandler = new _MemoryLimitsAwareHandler_190(); + customHandler.SetMaxNumberOfElementsInXrefStructure(1); + customHandler.SetMaxXObjectsSizePerPage(2); + customHandler.SetMaxSizeOfDecompressedPdfStreamsSum(3); + customHandler.SetMaxSizeOfSingleDecompressedPdfStream(4); + MemoryLimitsAwareHandler copy = customHandler.CreateNewInstance(); + NUnit.Framework.Assert.AreEqual(1, copy.GetMaxNumberOfElementsInXrefStructure()); + NUnit.Framework.Assert.AreEqual(2, copy.GetMaxXObjectsSizePerPage()); + NUnit.Framework.Assert.AreEqual(3, copy.GetMaxSizeOfDecompressedPdfStreamsSum()); + NUnit.Framework.Assert.AreEqual(4, copy.GetMaxSizeOfSingleDecompressedPdfStream()); + } + + private sealed class _MemoryLimitsAwareHandler_190 : MemoryLimitsAwareHandler { + public _MemoryLimitsAwareHandler_190() { + } + + public override MemoryLimitsAwareHandler CreateNewInstance() { + MemoryLimitsAwareHandler to = new MemoryLimitsAwareHandler(); + to.SetMaxSizeOfSingleDecompressedPdfStream(this.GetMaxSizeOfSingleDecompressedPdfStream()); + to.SetMaxSizeOfDecompressedPdfStreamsSum(this.GetMaxSizeOfDecompressedPdfStreamsSum()); + to.SetMaxNumberOfElementsInXrefStructure(this.GetMaxNumberOfElementsInXrefStructure()); + to.SetMaxXObjectsSizePerPage(this.GetMaxXObjectsSizePerPage()); + return to; + } + } + private static void TestSingleStream(MemoryLimitsAwareHandler handler) { String expectedExceptionMessage = KernelExceptionMessageConstant.DURING_DECOMPRESSION_SINGLE_STREAM_OCCUPIED_MORE_MEMORY_THAN_ALLOWED; int expectedFailureIndex = 10; diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PageFlushingTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PageFlushingTest.cs index df226af81c..1f496a859c 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PageFlushingTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PageFlushingTest.cs @@ -395,6 +395,10 @@ public virtual void Validate(IValidationContext validationContext) { page = ((PdfPageValidationContext)validationContext).GetPage(); } } + + public virtual bool IsPdfObjectReadyToFlush(PdfObject @object) { + return true; + } } private static void Test(String filename, PageFlushingTest.DocMode docMode, PageFlushingTest.FlushMode flushMode diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs index 15b1e5a27d..ffe06e8fef 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs @@ -586,6 +586,18 @@ public virtual void RemoveNestedDuplicatesHasChildInOrderArrayTest() { , "27 0 R"), e.Message); } + [NUnit.Framework.Test] + public virtual void CreatePdfDocumentWithAAndUaMetadataTest() { + String outputPdf = "pdfDocWithAAndUaMetadata.pdf"; + WriterProperties writerProperties = new WriterProperties().AddPdfAXmpMetadata(PdfAConformance.PDF_A_3A).AddPdfUaXmpMetadata + (PdfUAConformance.PDF_UA_1); + PdfDocument doc = new PdfDocument(new PdfWriter(DESTINATION_FOLDER + outputPdf, writerProperties)); + doc.AddNewPage(); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(DESTINATION_FOLDER + outputPdf, SOURCE_FOLDER + + "cmp_" + outputPdf, DESTINATION_FOLDER)); + } + private class IgnoreTagStructurePdfDocument : PdfDocument { //\cond DO_NOT_DOCUMENT internal IgnoreTagStructurePdfDocument(PdfReader reader) diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentUnitTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentUnitTest.cs index ceda1444be..7e5b4434c2 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentUnitTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentUnitTest.cs @@ -378,6 +378,10 @@ public virtual void Validate(IValidationContext validationContext) { documentValidationPerformed = true; } } + + public virtual bool IsPdfObjectReadyToFlush(PdfObject @object) { + return true; + } } } } diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfReaderTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfReaderTest.cs index 3c871f87c7..1d3fa66614 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfReaderTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfReaderTest.cs @@ -2374,10 +2374,7 @@ public virtual void StreamWithoutEndstreamKeywordConservativeModeTest() { String fileName = SOURCE_FOLDER + "NoEndstreamKeyword.pdf"; using (PdfReader reader = new PdfReader(fileName)) { reader.SetStrictnessLevel(PdfReader.StrictnessLevel.CONSERVATIVE); - PdfDocument pdfDocument = new PdfDocument(reader); - // Initialize xmp metadata, because we in reader mode in which xmp will be initialized only during closing - Exception exception = NUnit.Framework.Assert.Catch(typeof(PdfException), () => pdfDocument.GetXmpMetadata( - )); + Exception exception = NUnit.Framework.Assert.Catch(typeof(PdfException), () => new PdfDocument(reader)); NUnit.Framework.Assert.AreEqual(KernelExceptionMessageConstant.STREAM_SHALL_END_WITH_ENDSTREAM, exception. Message); PdfCatalog catalog = new PdfCatalog((PdfDictionary)reader.trailer.Get(PdfName.Root, true)); @@ -2535,14 +2532,14 @@ public virtual void StreamObjIsNullTest() { int objNumber = pdfDictionary.GetIndirectReference().objNr; pdfDocument.catalog.GetPdfObject().Put(PdfName.StructTreeRoot, pdfDictionary); pdfDocument.Close(); - PdfReader pdfReader = new _PdfReader_2853(objNumber, new MemoryStream(bsaos.ToArray())); + PdfReader pdfReader = new _PdfReader_2851(objNumber, new MemoryStream(bsaos.ToArray())); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => new PdfDocument(pdfReader)); NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(KernelExceptionMessageConstant.INVALID_OBJECT_STREAM_NUMBER , 5, 4, 492), e.Message); } - private sealed class _PdfReader_2853 : PdfReader { - public _PdfReader_2853(int objNumber, Stream baseArg1) + private sealed class _PdfReader_2851 : PdfReader { + public _PdfReader_2851(int objNumber, Stream baseArg1) : base(baseArg1) { this.objNumber = objNumber; } @@ -2561,7 +2558,7 @@ protected internal override PdfObject ReadObject(PdfIndirectReference reference) [NUnit.Framework.Test] public virtual void InitTagTreeStructureThrowsOOMIsCatched() { FileInfo file = new FileInfo(SOURCE_FOLDER + "big_table_lot_of_mcrs.pdf"); - MemoryLimitsAwareHandler memoryLimitsAwareHandler = new _MemoryLimitsAwareHandler_2872(); + MemoryLimitsAwareHandler memoryLimitsAwareHandler = new _MemoryLimitsAwareHandler_2870(); memoryLimitsAwareHandler.SetMaxSizeOfDecompressedPdfStreamsSum(100000); NUnit.Framework.Assert.Catch(typeof(MemoryLimitsAwareException), () => { using (PdfReader reader = new PdfReader(file, new ReaderProperties().SetMemoryLimitsAwareHandler(memoryLimitsAwareHandler @@ -2573,8 +2570,8 @@ public virtual void InitTagTreeStructureThrowsOOMIsCatched() { ); } - private sealed class _MemoryLimitsAwareHandler_2872 : MemoryLimitsAwareHandler { - public _MemoryLimitsAwareHandler_2872() { + private sealed class _MemoryLimitsAwareHandler_2870 : MemoryLimitsAwareHandler { + public _MemoryLimitsAwareHandler_2870() { } public override bool IsMemoryLimitsAwarenessRequiredOnDecompression(PdfArray filters) { diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/ReaderPropertiesTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/ReaderPropertiesTest.cs new file mode 100644 index 0000000000..e0be025dee --- /dev/null +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/ReaderPropertiesTest.cs @@ -0,0 +1,42 @@ +/* +This file is part of the iText (R) project. +Copyright (c) 1998-2024 Apryse Group NV +Authors: Apryse Software. + +This program is offered under a commercial and under the AGPL license. +For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. + +AGPL licensing: +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +using iText.Test; + +namespace iText.Kernel.Pdf { + [NUnit.Framework.Category("UnitTest")] + public class ReaderPropertiesTest : ExtendedITextTest { + [NUnit.Framework.Test] + public virtual void CopyConstructorTest() { + MemoryLimitsAwareHandler handler = new MemoryLimitsAwareHandler(); + handler.SetMaxXObjectsSizePerPage(10); + ReaderProperties properties = new ReaderProperties().SetPassword("123".GetBytes(iText.Commons.Utils.EncodingUtil.ISO_8859_1 + )).SetMemoryLimitsAwareHandler(handler); + ReaderProperties copy = new ReaderProperties(properties); + NUnit.Framework.Assert.AreEqual(copy.password, properties.password); + NUnit.Framework.Assert.AreNotEqual(copy.memoryLimitsAwareHandler, properties.memoryLimitsAwareHandler); + NUnit.Framework.Assert.AreEqual(copy.memoryLimitsAwareHandler.GetMaxXObjectsSizePerPage(), properties.memoryLimitsAwareHandler + .GetMaxXObjectsSizePerPage()); + NUnit.Framework.Assert.AreEqual(10, copy.memoryLimitsAwareHandler.GetMaxXObjectsSizePerPage()); + } + } +} diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/canvas/PdfCanvasUnitTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/canvas/PdfCanvasUnitTest.cs index 9c314c0f94..56a11c1db6 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/canvas/PdfCanvasUnitTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/canvas/PdfCanvasUnitTest.cs @@ -193,6 +193,10 @@ public virtual void Validate(IValidationContext validationContext) { gState = glyphsContext.GetGraphicsState(); } } + + public virtual bool IsPdfObjectReadyToFlush(PdfObject @object) { + return true; + } } } } diff --git a/itext.tests/itext.kernel.tests/itext/kernel/utils/ValidationContainerTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/utils/ValidationContainerTest.cs index 3127d6c37e..a37a69fb39 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/utils/ValidationContainerTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/utils/ValidationContainerTest.cs @@ -20,6 +20,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ +using iText.Kernel.Pdf; using iText.Kernel.Validation; using iText.Kernel.Validation.Context; using iText.Test; @@ -66,6 +67,10 @@ public virtual void Validate(IValidationContext validationContext) { objectValidationPerformed = true; } } + + public virtual bool IsPdfObjectReadyToFlush(PdfObject @object) { + return true; + } } } } diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_pdfDocWithAAndUaMetadata.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_pdfDocWithAAndUaMetadata.pdf new file mode 100644 index 0000000000..0a3149d4f2 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_pdfDocWithAAndUaMetadata.pdf differ diff --git a/itext.tests/itext.layout.tests/itext/layout/XMPWriterTest.cs b/itext.tests/itext.layout.tests/itext/layout/XMPWriterTest.cs index cc95e2cb79..bff812327c 100644 --- a/itext.tests/itext.layout.tests/itext/layout/XMPWriterTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/XMPWriterTest.cs @@ -83,8 +83,8 @@ public virtual void CreatePdfTest() { [NUnit.Framework.Test] public virtual void AddUAXMPMetaDataNotTaggedTest() { String fileName = "addUAXMPMetaDataNotTaggedTest.pdf"; - PdfDocument pdf = new PdfDocument(new PdfWriter(destinationFolder + fileName, new WriterProperties().AddUAXmpMetadata - ())); + WriterProperties writerProperties = new WriterProperties().AddPdfUaXmpMetadata(PdfUAConformance.PDF_UA_1); + PdfDocument pdf = new PdfDocument(new PdfWriter(destinationFolder + fileName, writerProperties)); ManipulatePdf(pdf, false); NUnit.Framework.Assert.IsNull(new CompareTool().CompareXmp(destinationFolder + fileName, sourceFolder + "cmp_" + fileName, true)); @@ -93,8 +93,8 @@ public virtual void AddUAXMPMetaDataNotTaggedTest() { [NUnit.Framework.Test] public virtual void AddUAXMPMetaDataTaggedTest() { String fileName = "addUAXMPMetaDataTaggedTest.pdf"; - PdfDocument pdf = new PdfDocument(new PdfWriter(destinationFolder + fileName, new WriterProperties().AddUAXmpMetadata - ())); + WriterProperties writerProperties = new WriterProperties().AddPdfUaXmpMetadata(PdfUAConformance.PDF_UA_1); + PdfDocument pdf = new PdfDocument(new PdfWriter(destinationFolder + fileName, writerProperties)); ManipulatePdf(pdf, true); NUnit.Framework.Assert.IsNull(new CompareTool().CompareXmp(destinationFolder + fileName, sourceFolder + "cmp_" + fileName, true)); diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/XMPWriterTest/cmp_addUAXMPMetaDataNotTaggedTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/XMPWriterTest/cmp_addUAXMPMetaDataNotTaggedTest.pdf index d7ea61b08e..53e7e0f0cc 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/XMPWriterTest/cmp_addUAXMPMetaDataNotTaggedTest.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/XMPWriterTest/cmp_addUAXMPMetaDataNotTaggedTest.pdf differ diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfA4CatalogCheckTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfA4CatalogCheckTest.cs index 4432430ee7..3ad2fae606 100644 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfA4CatalogCheckTest.cs +++ b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfA4CatalogCheckTest.cs @@ -188,6 +188,20 @@ public virtual void InvalidInfoTest() { , e.Message); } + [NUnit.Framework.Test] + public virtual void InvalidInfoWithFullCompression() { + String outPdf = destinationFolder + "invalidInfoWithFillCompression.pdf"; + PdfWriter writer = new PdfWriter(outPdf, new WriterProperties().SetPdfVersion(PdfVersion.PDF_2_0).SetFullCompressionMode + (true)); + Stream @is = FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"); + using (PdfADocument doc = new PdfADocument(writer, PdfAConformance.PDF_A_4, new PdfOutputIntent("Custom", + "", "http://www.color.org", "sRGB IEC61966-2.1", @is))) { + doc.AddNewPage(); + } + NUnit.Framework.Assert.IsNull(new VeraPdfValidator().Validate(outPdf)); + } + + // Android-Conversion-Skip-Line (TODO DEVSIX-7377 introduce pdf\a validation on Android) [NUnit.Framework.Test] public virtual void ReadValidDocumentTest() { String outPdf = destinationFolder + "simplePdfA4_output01.pdf"; @@ -302,10 +316,11 @@ public virtual void ValidFormXObjectTest() { // Android-Conversion-Skip-Line (TODO DEVSIX-7377 introduce pdf\a validation on Android) [NUnit.Framework.Test] public virtual void CreateInvalidPdfAVersionNumberWithPDFA4() { - PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties().SetPdfVersion(PdfVersion - .PDF_1_7)); - PdfADocument doc = new PdfADocument(writer, PdfAConformance.PDF_A_4, new PdfOutputIntent("Custom", "", "http://www.color.org" - , "sRGB IEC61966-2.1", FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties()); + PdfA4CatalogCheckTest.PdfDocumentCustomVersion doc = new PdfA4CatalogCheckTest.PdfDocumentCustomVersion(writer + , PdfAConformance.PDF_A_4, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1" + , FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + doc.SetPdfVersion(PdfVersion.PDF_1_7); doc.AddNewPage(); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => doc.Close()); NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(PdfaExceptionMessageConstant.THE_FILE_HEADER_SHALL_CONTAIN_RIGHT_PDF_VERSION @@ -314,10 +329,11 @@ public virtual void CreateInvalidPdfAVersionNumberWithPDFA4() { [NUnit.Framework.Test] public virtual void CreateInvalidPdfAVersionNumberWithPDFA4F() { - PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties().SetPdfVersion(PdfVersion - .PDF_1_7)); - PdfADocument doc = new PdfADocument(writer, PdfAConformance.PDF_A_4F, new PdfOutputIntent("Custom", "", "http://www.color.org" - , "sRGB IEC61966-2.1", FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties()); + PdfA4CatalogCheckTest.PdfDocumentCustomVersion doc = new PdfA4CatalogCheckTest.PdfDocumentCustomVersion(writer + , PdfAConformance.PDF_A_4F, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1" + , FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + doc.SetPdfVersion(PdfVersion.PDF_1_7); doc.AddNewPage(); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => doc.Close()); NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(PdfaExceptionMessageConstant.THE_FILE_HEADER_SHALL_CONTAIN_RIGHT_PDF_VERSION @@ -326,10 +342,11 @@ public virtual void CreateInvalidPdfAVersionNumberWithPDFA4F() { [NUnit.Framework.Test] public virtual void CreateInvalidPdfAVersionNumberWithPDFA4E() { - PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties().SetPdfVersion(PdfVersion - .PDF_1_7)); - PdfADocument doc = new PdfADocument(writer, PdfAConformance.PDF_A_4E, new PdfOutputIntent("Custom", "", "http://www.color.org" - , "sRGB IEC61966-2.1", FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties()); + PdfA4CatalogCheckTest.PdfDocumentCustomVersion doc = new PdfA4CatalogCheckTest.PdfDocumentCustomVersion(writer + , PdfAConformance.PDF_A_4E, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1" + , FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + doc.SetPdfVersion(PdfVersion.PDF_1_7); doc.AddNewPage(); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => doc.Close()); NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(PdfaExceptionMessageConstant.THE_FILE_HEADER_SHALL_CONTAIN_RIGHT_PDF_VERSION @@ -338,10 +355,11 @@ public virtual void CreateInvalidPdfAVersionNumberWithPDFA4E() { [NUnit.Framework.Test] public virtual void CreateInvalidPdfAVersion16NumberWithPDFA4() { - PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties().SetPdfVersion(PdfVersion - .PDF_1_6)); - PdfADocument doc = new PdfADocument(writer, PdfAConformance.PDF_A_4, new PdfOutputIntent("Custom", "", "http://www.color.org" - , "sRGB IEC61966-2.1", FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties()); + PdfA4CatalogCheckTest.PdfDocumentCustomVersion doc = new PdfA4CatalogCheckTest.PdfDocumentCustomVersion(writer + , PdfAConformance.PDF_A_4, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1" + , FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + doc.SetPdfVersion(PdfVersion.PDF_1_6); doc.AddNewPage(); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => doc.Close()); NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(PdfaExceptionMessageConstant.THE_FILE_HEADER_SHALL_CONTAIN_RIGHT_PDF_VERSION @@ -350,10 +368,11 @@ public virtual void CreateInvalidPdfAVersion16NumberWithPDFA4() { [NUnit.Framework.Test] public virtual void CreateInvalidPdfAVersion13NumberWithPDFA4F() { - PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties().SetPdfVersion(PdfVersion - .PDF_1_3)); - PdfADocument doc = new PdfADocument(writer, PdfAConformance.PDF_A_4F, new PdfOutputIntent("Custom", "", "http://www.color.org" - , "sRGB IEC61966-2.1", FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties()); + PdfA4CatalogCheckTest.PdfDocumentCustomVersion doc = new PdfA4CatalogCheckTest.PdfDocumentCustomVersion(writer + , PdfAConformance.PDF_A_4F, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1" + , FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + doc.SetPdfVersion(PdfVersion.PDF_1_3); doc.AddNewPage(); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => doc.Close()); NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(PdfaExceptionMessageConstant.THE_FILE_HEADER_SHALL_CONTAIN_RIGHT_PDF_VERSION @@ -362,14 +381,26 @@ public virtual void CreateInvalidPdfAVersion13NumberWithPDFA4F() { [NUnit.Framework.Test] public virtual void CreateInvalidPdfAVersionNumber17WithPDFA4E() { - PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties().SetPdfVersion(PdfVersion - .PDF_1_7)); - PdfADocument doc = new PdfADocument(writer, PdfAConformance.PDF_A_4E, new PdfOutputIntent("Custom", "", "http://www.color.org" - , "sRGB IEC61966-2.1", FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + PdfWriter writer = new PdfWriter(new PdfWriter(new MemoryStream()), new WriterProperties()); + PdfA4CatalogCheckTest.PdfDocumentCustomVersion doc = new PdfA4CatalogCheckTest.PdfDocumentCustomVersion(writer + , PdfAConformance.PDF_A_4E, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1" + , FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm"))); + doc.SetPdfVersion(PdfVersion.PDF_1_7); doc.AddNewPage(); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => doc.Close()); NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(PdfaExceptionMessageConstant.THE_FILE_HEADER_SHALL_CONTAIN_RIGHT_PDF_VERSION , "2"), e.Message); } + + private class PdfDocumentCustomVersion : PdfADocument { + public PdfDocumentCustomVersion(PdfWriter writer, PdfAConformance aConformance, PdfOutputIntent outputIntent + ) + : base(writer, aConformance, outputIntent) { + } + + public virtual void SetPdfVersion(PdfVersion pdfVersion) { + this.pdfVersion = pdfVersion; + } + } } } diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAAgnosticPdfDocumentUnitTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAAgnosticPdfDocumentUnitTest.cs deleted file mode 100644 index 62f03dac94..0000000000 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAAgnosticPdfDocumentUnitTest.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* -This file is part of the iText (R) project. -Copyright (c) 1998-2024 Apryse Group NV -Authors: Apryse Software. - -This program is offered under a commercial and under the AGPL license. -For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. - -AGPL licensing: -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ -using System; -using System.Collections.Generic; -using iText.IO.Source; -using iText.Kernel.Font; -using iText.Kernel.Pdf; -using iText.Kernel.Validation; -using iText.Kernel.Validation.Context; -using iText.Kernel.XMP; -using iText.Pdfa.Logs; -using iText.Test; -using iText.Test.Attributes; - -namespace iText.Pdfa { - [NUnit.Framework.Category("UnitTest")] - public class PdfAAgnosticPdfDocumentUnitTest : ExtendedITextTest { - public static readonly String sourceFolder = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext - .CurrentContext.TestDirectory) + "/resources/itext/pdfa/"; - - public static readonly String destinationFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory - + "/test/itext/pdfa/AgnosticPdfDocumentUnitTest/"; - - [NUnit.Framework.OneTimeSetUp] - public static void BeforeClass() { - CreateOrClearDestinationFolder(destinationFolder); - } - - [NUnit.Framework.Test] - public virtual void LoadPdfDocumentTest() { - PdfAAgnosticPdfDocumentUnitTest.TestAgnosticPdfDocument pdfDoc = new PdfAAgnosticPdfDocumentUnitTest.TestAgnosticPdfDocument - (this, new PdfReader(sourceFolder + "pdfs/simpleDoc.pdf"), new PdfWriter(new ByteArrayOutputStream())); - pdfDoc.FlushObjectPublic(pdfDoc.GetPage(1).GetPdfObject(), true); - NUnit.Framework.Assert.IsTrue(pdfDoc.GetPage(1).GetPdfObject().IsFlushed()); - IValidationContext validationContext = new PdfDocumentValidationContext(pdfDoc, new List()); - pdfDoc.CheckIsoConformance(validationContext); - // Does nothing for PdfDocument - NUnit.Framework.Assert.IsFalse(pdfDoc.GetPageFactoryPublic() is PdfAPageFactory); - NUnit.Framework.Assert.IsNotNull(pdfDoc.GetConformance()); - NUnit.Framework.Assert.IsFalse(pdfDoc.GetConformance().IsPdfAOrUa()); - pdfDoc.UpdateXmpMetadataPublic(); - XMPMeta xmpMeta = pdfDoc.GetXmpMetadata(true); - NUnit.Framework.Assert.IsNull(xmpMeta.GetProperty(XMPConst.NS_PDFA_ID, XMPConst.PART)); - NUnit.Framework.Assert.IsNull(xmpMeta.GetProperty(XMPConst.NS_PDFA_ID, XMPConst.CONFORMANCE)); - pdfDoc.Close(); - } - - [NUnit.Framework.Test] - public virtual void GetDefaultFont() { - PdfAAgnosticPdfDocumentUnitTest.TestAgnosticPdfDocument pdfDoc = new PdfAAgnosticPdfDocumentUnitTest.TestAgnosticPdfDocument - (this, new PdfReader(sourceFolder + "pdfs/simpleDoc.pdf"), new PdfWriter(new ByteArrayOutputStream())); - NUnit.Framework.Assert.IsNotNull(pdfDoc.GetDefaultFont()); - } - - [NUnit.Framework.Test] - [LogMessage(PdfALogMessageConstant.PDFA_OBJECT_FLUSHING_WAS_NOT_PERFORMED)] - public virtual void LoadPdfADocumentTest() { - PdfAAgnosticPdfDocumentUnitTest.TestAgnosticPdfDocument pdfADoc = new PdfAAgnosticPdfDocumentUnitTest.TestAgnosticPdfDocument - (this, new PdfReader(sourceFolder + "pdfs/pdfa.pdf"), new PdfWriter(new ByteArrayOutputStream()), new - StampingProperties()); - pdfADoc.FlushObjectPublic(pdfADoc.GetPage(1).GetPdfObject(), true); - NUnit.Framework.Assert.IsFalse(pdfADoc.GetPage(1).GetPdfObject().IsFlushed()); - IValidationContext validationContext = new PdfDocumentValidationContext(pdfADoc, new List()); - pdfADoc.CheckIsoConformance(validationContext); - NUnit.Framework.Assert.AreEqual(PdfAConformance.PDF_A_2B, pdfADoc.GetConformance().GetAConformance()); - NUnit.Framework.Assert.IsTrue(pdfADoc.GetPageFactoryPublic() is PdfAPageFactory); - pdfADoc.UpdateXmpMetadataPublic(); - XMPMeta xmpMeta = pdfADoc.GetXmpMetadata(); - NUnit.Framework.Assert.IsNotNull(xmpMeta.GetProperty(XMPConst.NS_PDFA_ID, XMPConst.PART)); - NUnit.Framework.Assert.IsNotNull(xmpMeta.GetProperty(XMPConst.NS_PDFA_ID, XMPConst.CONFORMANCE)); - // Extra PdfA error message check - pdfADoc.FlushObjectPublic(pdfADoc.GetCatalog().GetPdfObject(), true); - NUnit.Framework.Assert.IsFalse(pdfADoc.GetCatalog().GetPdfObject().IsFlushed()); - pdfADoc.Close(); - } - - private class TestAgnosticPdfDocument : PdfAAgnosticPdfDocument { - public TestAgnosticPdfDocument(PdfAAgnosticPdfDocumentUnitTest _enclosing, PdfReader reader, PdfWriter writer - ) - : base(reader, writer, new StampingProperties()) { - this._enclosing = _enclosing; - } - - public TestAgnosticPdfDocument(PdfAAgnosticPdfDocumentUnitTest _enclosing, PdfReader reader, PdfWriter writer - , StampingProperties properties) - : base(reader, writer, properties) { - this._enclosing = _enclosing; - } - - public virtual IPdfPageFactory GetPageFactoryPublic() { - return base.GetPageFactory(); - } - - public virtual void UpdateXmpMetadataPublic() { - base.UpdateXmpMetadata(); - } - - public virtual void FlushObjectPublic(PdfObject pdfObject, bool canBeInObjStm) { - base.FlushObject(pdfObject, canBeInObjStm); - } - - private readonly PdfAAgnosticPdfDocumentUnitTest _enclosing; - } - } -} diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfADocumentTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfADocumentTest.cs index 606a9b890d..f3b447bcf8 100644 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfADocumentTest.cs +++ b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfADocumentTest.cs @@ -26,7 +26,9 @@ You should have received a copy of the GNU Affero General Public License using iText.Kernel.Pdf; using iText.Kernel.Validation.Context; using iText.Pdfa.Exceptions; +using iText.Pdfa.Logs; using iText.Test; +using iText.Test.Attributes; namespace iText.Pdfa { [NUnit.Framework.Category("UnitTest")] @@ -56,5 +58,29 @@ public virtual void CheckCMSSignatureTypeIsoConformance() { NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.SIGNATURE_SHALL_CONFORM_TO_ONE_OF_THE_PADES_PROFILE , e.Message); } + + [NUnit.Framework.Test] + public virtual void OpeningNonADocumentWithPdfADocumentTest() { + MemoryStream os = new MemoryStream(); + using (PdfDocument pdfDocument = new PdfDocument(new PdfWriter(os))) { + pdfDocument.AddNewPage(); + } + Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => new PdfADocument(new PdfReader + (new MemoryStream(os.ToArray())), new PdfWriter(new MemoryStream()))); + NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.DOCUMENT_TO_READ_FROM_SHALL_BE_A_PDFA_CONFORMANT_FILE_WITH_VALID_XMP_METADATA + , e.Message); + } + + [NUnit.Framework.Test] + [LogMessage(PdfALogMessageConstant.WRITER_PROPERTIES_PDF_VERSION_WAS_OVERRIDDEN, LogLevel = LogLevelConstants + .WARN)] + public virtual void SettingWrongPdfVersionTest() { + Stream @is = FileUtil.GetInputStreamForFile(SOURCE_FOLDER + "sRGB Color Space Profile.icm"); + PdfOutputIntent outputIntent = new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1" + , @is); + PdfADocument doc = new PdfADocument(new PdfWriter(new MemoryStream(), new WriterProperties().SetPdfVersion + (PdfVersion.PDF_1_4)), PdfAConformance.PDF_A_4, outputIntent); + doc.Close(); + } } } diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAIndirectObjectsCountLimitTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAIndirectObjectsCountLimitTest.cs index f03f92f297..4d28c16ad1 100644 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAIndirectObjectsCountLimitTest.cs +++ b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAIndirectObjectsCountLimitTest.cs @@ -26,6 +26,7 @@ You should have received a copy of the GNU Affero General Public License using iText.IO.Font; using iText.Kernel.Font; using iText.Kernel.Pdf; +using iText.Kernel.Validation; using iText.Layout; using iText.Layout.Element; using iText.Pdfa.Checker; @@ -40,21 +41,23 @@ public class PdfAIndirectObjectsCountLimitTest : ExtendedITextTest { [NUnit.Framework.Test] public virtual void ValidAmountOfIndirectObjectsTest() { - PdfA1Checker testChecker = new _PdfA1Checker_57(PdfAConformance.PDF_A_1B); + PdfA1Checker testChecker = new _PdfA1Checker_58(PdfAConformance.PDF_A_1B); using (Stream icm = FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm")) { using (Stream fos = new MemoryStream()) { using (Document document = new Document(new PdfADocument(new PdfWriter(fos), PdfAConformance.PDF_A_1B, GetOutputIntent (icm)))) { PdfADocument pdfa = (PdfADocument)document.GetPdfDocument(); - pdfa.checker = testChecker; + ValidationContainer container = new ValidationContainer(); + container.AddChecker(testChecker); + pdfa.GetDiContainer().Register(typeof(ValidationContainer), container); document.Add(BuildContent()); } } } } - private sealed class _PdfA1Checker_57 : PdfA1Checker { - public _PdfA1Checker_57(PdfAConformance baseArg1) + private sealed class _PdfA1Checker_58 : PdfA1Checker { + public _PdfA1Checker_58(PdfAConformance baseArg1) : base(baseArg1) { } @@ -67,13 +70,15 @@ protected internal override long GetMaxNumberOfIndirectObjects() { // limit per "mock specification" conformance exception shouldn't be thrown [NUnit.Framework.Test] public virtual void InvalidAmountOfIndirectObjectsTest() { - PdfA1Checker testChecker = new _PdfA1Checker_82(PdfAConformance.PDF_A_1B); + PdfA1Checker testChecker = new _PdfA1Checker_85(PdfAConformance.PDF_A_1B); using (Stream icm = FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm")) { using (Stream fos = new MemoryStream()) { Document document = new Document(new PdfADocument(new PdfWriter(fos), PdfAConformance.PDF_A_1B, GetOutputIntent (icm))); PdfADocument pdfa = (PdfADocument)document.GetPdfDocument(); - pdfa.checker = testChecker; + ValidationContainer container = new ValidationContainer(); + container.AddChecker(testChecker); + pdfa.GetDiContainer().Register(typeof(ValidationContainer), container); document.Add(BuildContent()); // generated document contains exactly 10 indirect objects. Given 9 is the allowed // limit per "mock specification" conformance exception should be thrown as the limit @@ -85,8 +90,8 @@ public virtual void InvalidAmountOfIndirectObjectsTest() { } } - private sealed class _PdfA1Checker_82 : PdfA1Checker { - public _PdfA1Checker_82(PdfAConformance baseArg1) + private sealed class _PdfA1Checker_85 : PdfA1Checker { + public _PdfA1Checker_85(PdfAConformance baseArg1) : base(baseArg1) { } @@ -97,12 +102,14 @@ protected internal override long GetMaxNumberOfIndirectObjects() { [NUnit.Framework.Test] public virtual void InvalidAmountOfIndirectObjectsAppendModeTest() { - PdfA1Checker testChecker = new _PdfA1Checker_110(PdfAConformance.PDF_A_1B); + PdfA1Checker testChecker = new _PdfA1Checker_115(PdfAConformance.PDF_A_1B); using (Stream fis = FileUtil.GetInputStreamForFile(sourceFolder + "pdfs/pdfa10IndirectObjects.pdf")) { using (Stream fos = new MemoryStream()) { PdfADocument pdfa = new PdfADocument(new PdfReader(fis), new PdfWriter(fos), new StampingProperties().UseAppendMode ()); - pdfa.checker = testChecker; + ValidationContainer container = new ValidationContainer(); + container.AddChecker(testChecker); + pdfa.GetDiContainer().Register(typeof(ValidationContainer), container); pdfa.AddNewPage(); // during closing of pdfa object exception will be thrown as new document will contain // 12 indirect objects and limit per "mock specification" conformance will be exceeded @@ -113,8 +120,8 @@ public virtual void InvalidAmountOfIndirectObjectsAppendModeTest() { } } - private sealed class _PdfA1Checker_110 : PdfA1Checker { - public _PdfA1Checker_110(PdfAConformance baseArg1) + private sealed class _PdfA1Checker_115 : PdfA1Checker { + public _PdfA1Checker_115(PdfAConformance baseArg1) : base(baseArg1) { } diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAPageTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAPageTest.cs index 8e2c77171d..c4e23f8f57 100644 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAPageTest.cs +++ b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAPageTest.cs @@ -25,6 +25,8 @@ You should have received a copy of the GNU Affero General Public License using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Event; +using iText.Kernel.Validation; +using iText.Kernel.Validation.Context; using iText.Layout; using iText.Layout.Element; using iText.Pdfa.Logs; @@ -162,7 +164,7 @@ public virtual void CheckFlushingOfCheckedPage() { int pageCount = 3; for (int i = 0; i < pageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); - pdfDoc.checker.CheckSinglePage(page); + pdfDoc.GetDiContainer().GetInstance().Validate(new PdfPageValidationContext(page)); page.Flush(false); } NUnit.Framework.Assert.AreEqual(pageCount, pdfDoc.GetNumberOfPages()); diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAXmpTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAXmpTest.cs index 4f4fe73211..f371aa5061 100644 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAXmpTest.cs +++ b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAXmpTest.cs @@ -137,13 +137,14 @@ public virtual void TestPdfUAIdSchemaNameSpaceUriIsNotText() { } private void GeneratePdfAWithUA(Stream os) { - WriterProperties wp = new WriterProperties().AddUAXmpMetadata(); + WriterProperties wp = new WriterProperties().AddPdfUaXmpMetadata(PdfUAConformance.PDF_UA_1); using (PdfWriter w = new PdfWriter(os, wp)) { PdfOutputIntent outputIntent; using (Stream @is = FileUtil.GetInputStreamForFile(sourceFolder + "sRGB Color Space Profile.icm")) { outputIntent = new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", @is); } - PdfDocument pdfDoc = new PdfADocument(w, PdfAConformance.PDF_A_2A, outputIntent).SetTagged(); + PdfDocument pdfDoc = new PdfADocument(w, PdfAConformance.PDF_A_2A, outputIntent); + pdfDoc.SetTagged(); pdfDoc.GetDocumentInfo().SetTitle("Test document"); pdfDoc.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true)); pdfDoc.GetCatalog().SetLang(new PdfString("en")); diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/checker/PdfA1CheckerTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/checker/PdfA1CheckerTest.cs index b3971494ad..51832a0d0a 100644 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/checker/PdfA1CheckerTest.cs +++ b/itext.tests/itext.pdfa.tests/itext/pdfa/checker/PdfA1CheckerTest.cs @@ -98,7 +98,7 @@ public virtual void DeprecatedCheckColorShadingTest() { public virtual void CheckSignatureTest() { PdfDictionary dict = new PdfDictionary(); pdfA1Checker.CheckSignature(dict); - NUnit.Framework.Assert.IsTrue(pdfA1Checker.ObjectIsChecked(dict)); + NUnit.Framework.Assert.IsTrue(pdfA1Checker.IsPdfObjectReadyToFlush(dict)); } [NUnit.Framework.Test] diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/checker/PdfA2CheckerTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/checker/PdfA2CheckerTest.cs index caaf749d3b..3e2fbea7fd 100644 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/checker/PdfA2CheckerTest.cs +++ b/itext.tests/itext.pdfa.tests/itext/pdfa/checker/PdfA2CheckerTest.cs @@ -349,7 +349,7 @@ public virtual void CheckColorShadingWithoutExtGStatePropertyInPatternDictTest() public virtual void CheckSignatureTest() { PdfDictionary signatureDict = CreateSignatureDict(); pdfA2Checker.CheckSignature(signatureDict); - NUnit.Framework.Assert.IsTrue(pdfA2Checker.ObjectIsChecked(signatureDict)); + NUnit.Framework.Assert.IsTrue(pdfA2Checker.IsPdfObjectReadyToFlush(signatureDict)); } [NUnit.Framework.Test] diff --git a/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfA1AnnotationCheckTest/cmp_pdfA1a_annotationCheckTest09.pdf b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfA1AnnotationCheckTest/cmp_pdfA1a_annotationCheckTest09.pdf index 1d94298d1b..19f2793d77 100644 Binary files a/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfA1AnnotationCheckTest/cmp_pdfA1a_annotationCheckTest09.pdf and b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfA1AnnotationCheckTest/cmp_pdfA1a_annotationCheckTest09.pdf differ diff --git a/itext.tests/itext.pdfua.tests/itext.pdfua.tests.csproj b/itext.tests/itext.pdfua.tests/itext.pdfua.tests.csproj index 2f89f75272..77b9aa70a7 100644 --- a/itext.tests/itext.pdfua.tests/itext.pdfua.tests.csproj +++ b/itext.tests/itext.pdfua.tests/itext.pdfua.tests.csproj @@ -39,8 +39,7 @@ - - + diff --git a/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUADocumentTest.cs b/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUADocumentTest.cs index 42424e568f..c841e499d1 100644 --- a/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUADocumentTest.cs +++ b/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUADocumentTest.cs @@ -40,5 +40,14 @@ public virtual void OpenNotUaDocumentTest() { NUnit.Framework.Assert.DoesNotThrow(() => new PdfUADocument(new PdfReader(SOURCE_FOLDER + "usualPdf.pdf"), new PdfWriter(new MemoryStream()), new PdfUAConfig(PdfUAConformance.PDF_UA_1, "simple doc", "eng"))); } + + [NUnit.Framework.Test] + [LogMessage(PdfUALogMessageConstants.WRITER_PROPERTIES_PDF_VERSION_WAS_OVERRIDDEN, LogLevel = LogLevelConstants + .WARN)] + public virtual void SettingWrongPdfVersionTest() { + PdfUADocument doc = new PdfUADocument(new PdfWriter(new MemoryStream(), new WriterProperties().SetPdfVersion + (PdfVersion.PDF_1_4)), new PdfUAConfig(PdfUAConformance.PDF_UA_1, "en-us", "title")); + doc.Close(); + } } } diff --git a/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUAMetadataUnitTest.cs b/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUAMetadataUnitTest.cs index 85f2ed3608..d65977270d 100644 --- a/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUAMetadataUnitTest.cs +++ b/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUAMetadataUnitTest.cs @@ -101,8 +101,9 @@ public virtual void DocumentWithInvalidMetadataTypeTest() { [NUnit.Framework.Test] public virtual void DocumentWithInvalidPdfVersionTest() { - PdfDocument pdfDocument = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties( - ).SetPdfVersion(PdfVersion.PDF_2_0))); + PdfUAMetadataUnitTest.PdfDocumentCustomVersion pdfDocument = new PdfUAMetadataUnitTest.PdfDocumentCustomVersion + (new PdfWriter(new MemoryStream()), new PdfUAConfig(PdfUAConformance.PDF_UA_1, "en-us", "title")); + pdfDocument.SetPdfVersion(PdfVersion.PDF_2_0); pdfDocument.AddNewPage(); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfUAConformanceException), () => pdfDocument.Close()); NUnit.Framework.Assert.AreEqual(PdfUAExceptionMessageConstants.INVALID_PDF_VERSION, e.Message); @@ -139,5 +140,15 @@ protected internal override void CheckMetadata(PdfCatalog catalog) { base.CheckMetadata(catalog); } } + + private class PdfDocumentCustomVersion : PdfUADocument { + public PdfDocumentCustomVersion(PdfWriter writer, PdfUAConfig config) + : base(writer, config) { + } + + public virtual void SetPdfVersion(PdfVersion pdfVersion) { + this.pdfVersion = pdfVersion; + } + } } } diff --git a/itext.tests/itext.pdfua.tests/itext/pdfua/PemFileHelper.cs b/itext.tests/itext.pdfua.tests/itext/pdfua/PemFileHelper.cs deleted file mode 100644 index 7ea4d23d6f..0000000000 --- a/itext.tests/itext.pdfua.tests/itext/pdfua/PemFileHelper.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* -This file is part of the iText (R) project. -Copyright (c) 1998-2024 Apryse Group NV -Authors: Apryse Software. - -This program is offered under a commercial and under the AGPL license. -For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. - -AGPL licensing: -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using iText.Bouncycastleconnector; -using iText.Commons.Bouncycastle; -using iText.Commons.Bouncycastle.Cert; -using iText.Commons.Bouncycastle.Crypto; -using iText.Commons.Bouncycastle.Openssl; - -namespace iText.Pdfua { - public sealed class PemFileHelper { - private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory(); - - private PemFileHelper() { - // Empty constructor. - } - - public static IX509Certificate[] ReadFirstChain(String pemFileName) { - return ReadCertificates(pemFileName).ToArray(); - } - - public static IPrivateKey ReadFirstKey(String pemFileName, char[] keyPass) { - return ReadPrivateKey(pemFileName, keyPass); - } - - public static List InitStore(String pemFileName) { - IX509Certificate[] chain = ReadFirstChain(pemFileName); - return chain.Length > 0 ? new List { chain[0] } : chain.ToList(); - } - - private static IList ReadCertificates(String pemFileName) { - using (TextReader file = new StreamReader(pemFileName)) { - IPemReader parser = FACTORY.CreatePEMParser(file, null); - Object readObject = parser.ReadObject(); - IList certificates = new List(); - while (readObject != null) { - if (readObject is IX509Certificate) { - certificates.Add((IX509Certificate)readObject); - } - readObject = parser.ReadObject(); - } - return certificates; - } - } - - private static IPrivateKey ReadPrivateKey(String pemFileName, char[] keyPass) { - using (TextReader file = new StreamReader(pemFileName)) { - IPemReader parser = FACTORY.CreatePEMParser(file, keyPass); - Object readObject = parser.ReadObject(); - while (!(readObject is IPrivateKey) && readObject != null) { - readObject = parser.ReadObject(); - } - return (IPrivateKey)readObject; - } - } - } -} diff --git a/itext.tests/itext.pdfua.tests/itext/pdfua/checkers/PdfUAGraphicsTest.cs b/itext.tests/itext.pdfua.tests/itext/pdfua/checkers/PdfUAGraphicsTest.cs index 6d44435246..4de3074705 100644 --- a/itext.tests/itext.pdfua.tests/itext/pdfua/checkers/PdfUAGraphicsTest.cs +++ b/itext.tests/itext.pdfua.tests/itext/pdfua/checkers/PdfUAGraphicsTest.cs @@ -68,8 +68,7 @@ public virtual void InitializeFramework() { [NUnit.Framework.Test] public virtual void ImageWithoutAlternativeDescription_ThrowsInLayout() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); Document document = new Document(pdfDoc); iText.Layout.Element.Image img = new Image(ImageDataFactory.Create(DOG)); Exception e = NUnit.Framework.Assert.Catch(typeof(PdfUAConformanceException), () => { @@ -86,8 +85,7 @@ public virtual void LayoutCheckUtilTest() { [NUnit.Framework.Test] public virtual void ImageWithEmptyAlternativeDescription_ThrowsInLayout() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); Document document = new Document(pdfDoc); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); img.GetAccessibilityProperties().SetAlternateDescription(""); @@ -105,12 +103,12 @@ public virtual void ImageCustomRole_Ok() { root.AddRoleMapping("CustomImage", StandardRoles.FIGURE); } ); - framework.AddSuppliers(new _Generator_126()); + framework.AddSuppliers(new _Generator_121()); framework.AssertBothValid("imageWithCustomRoleOk"); } - private sealed class _Generator_126 : UaValidationTestFramework.Generator { - public _Generator_126() { + private sealed class _Generator_121 : UaValidationTestFramework.Generator { + public _Generator_121() { } public IBlockElement Generate() { @@ -135,12 +133,12 @@ public virtual void ImageCustomDoubleMapping_Ok() { root.AddRoleMapping("CustomImage2", "CustomImage"); } ); - framework.AddSuppliers(new _Generator_150()); + framework.AddSuppliers(new _Generator_145()); framework.AssertBothValid("imageWithDoubleMapping"); } - private sealed class _Generator_150 : UaValidationTestFramework.Generator { - public _Generator_150() { + private sealed class _Generator_145 : UaValidationTestFramework.Generator { + public _Generator_145() { } public IBlockElement Generate() { @@ -164,12 +162,12 @@ public virtual void ImageCustomRoleNoAlternateDescription_Throws() { root.AddRoleMapping("CustomImage", StandardRoles.FIGURE); } ); - framework.AddSuppliers(new _Generator_173()); + framework.AddSuppliers(new _Generator_168()); framework.AssertBothFail("imageWithCustomRoleAndNoDescription"); } - private sealed class _Generator_173 : UaValidationTestFramework.Generator { - public _Generator_173() { + private sealed class _Generator_168 : UaValidationTestFramework.Generator { + public _Generator_168() { } public IBlockElement Generate() { @@ -193,12 +191,12 @@ public virtual void ImageCustomDoubleMapping_Throws() { root.AddRoleMapping("CustomImage2", "CustomImage"); } ); - framework.AddSuppliers(new _Generator_196()); + framework.AddSuppliers(new _Generator_191()); framework.AssertBothFail("imageCustomDoubleMapping_Throws"); } - private sealed class _Generator_196 : UaValidationTestFramework.Generator { - public _Generator_196() { + private sealed class _Generator_191 : UaValidationTestFramework.Generator { + public _Generator_191() { } public IBlockElement Generate() { @@ -217,8 +215,7 @@ public IBlockElement Generate() { [NUnit.Framework.Test] public virtual void ImageWithValidAlternativeDescription_OK() { String OUTPUT_FILE = DESTINATION_FOLDER + "imageWithValidAlternativeDescription_OK.pdf"; - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(OUTPUT_FILE, new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(OUTPUT_FILE)); Document document = new Document(pdfDoc); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); img.GetAccessibilityProperties().SetAlternateDescription("Alternative description"); @@ -233,8 +230,7 @@ public virtual void ImageWithValidAlternativeDescription_OK() { [NUnit.Framework.Test] public virtual void ImageWithValidActualText_OK() { String OUTPUT_FILE = DESTINATION_FOLDER + "imageWithValidActualText_OK.pdf"; - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(OUTPUT_FILE, new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(OUTPUT_FILE)); Document document = new Document(pdfDoc); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); img.GetAccessibilityProperties().SetActualText("Actual text"); @@ -249,8 +245,7 @@ public virtual void ImageWithValidActualText_OK() { [NUnit.Framework.Test] public virtual void ImageWithCaption_OK() { String OUTPUT_FILE = DESTINATION_FOLDER + "imageWithCaption_OK.pdf"; - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(OUTPUT_FILE, new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(OUTPUT_FILE)); Document document = new Document(pdfDoc); Div imgWithCaption = new Div(); imgWithCaption.GetAccessibilityProperties().SetRole(StandardRoles.FIGURE); @@ -272,8 +267,7 @@ public virtual void ImageWithCaption_OK() { [NUnit.Framework.Test] public virtual void ImageWithCaptionWithoutAlternateDescription_Throws() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); Document document = new Document(pdfDoc); Div imgWithCaption = new Div(); imgWithCaption.GetAccessibilityProperties().SetRole(StandardRoles.FIGURE); @@ -295,8 +289,7 @@ public virtual void ImageWithCaptionWithoutAlternateDescription_Throws() { [NUnit.Framework.Test] public virtual void ImageWithoutActualText_ThrowsInLayout() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); Document document = new Document(pdfDoc); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); img.GetAccessibilityProperties().SetActualText(null); @@ -309,8 +302,7 @@ public virtual void ImageWithoutActualText_ThrowsInLayout() { [NUnit.Framework.Test] public virtual void ImageWithEmptyActualText_ThrowsInLayout() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); Document document = new Document(pdfDoc); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); img.GetAccessibilityProperties().SetActualText(""); @@ -320,8 +312,7 @@ public virtual void ImageWithEmptyActualText_ThrowsInLayout() { [NUnit.Framework.Test] public virtual void ImageDirectlyOnCanvas_OK() { String OUTPUT_FILE = DESTINATION_FOLDER + "imageDirectlyOnCanvas_OK.pdf"; - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(OUTPUT_FILE, new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(OUTPUT_FILE)); Document document = new Document(pdfDoc); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); img.GetAccessibilityProperties().SetAlternateDescription("Hello"); @@ -352,8 +343,7 @@ public virtual void ImageDirectlyOnCanvas_OK() { [NUnit.Framework.Test] public virtual void ImageDirectlyOnCanvasWithoutAlternateDescription_ThrowsOnClose() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); TagTreePointer pointerForImage = new TagTreePointer(pdfDoc); PdfPage page = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); @@ -371,8 +361,7 @@ public virtual void ImageDirectlyOnCanvasWithoutAlternateDescription_ThrowsOnClo [NUnit.Framework.Test] public virtual void ImageDirectlyOnCanvasWithEmptyActualText_OK() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); TagTreePointer pointerForImage = new TagTreePointer(pdfDoc); PdfPage page = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); @@ -387,8 +376,7 @@ public virtual void ImageDirectlyOnCanvasWithEmptyActualText_OK() { [NUnit.Framework.Test] public virtual void TestOverflowImage() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); Document document = new Document(pdfDoc); document.Add(new Div().SetHeight(730).SetBackgroundColor(ColorConstants.CYAN)); @@ -400,8 +388,7 @@ public virtual void TestOverflowImage() { [NUnit.Framework.Test] public virtual void TestEmbeddedImageInTable() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); Document document = new Document(pdfDoc); Table table = new Table(2); @@ -417,8 +404,7 @@ public virtual void TestEmbeddedImageInTable() { [NUnit.Framework.Test] public virtual void TestEmbeddedImageInDiv() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); Document document = new Document(pdfDoc); Div div = new Div(); @@ -431,8 +417,7 @@ public virtual void TestEmbeddedImageInDiv() { [NUnit.Framework.Test] public virtual void TestEmbeddedImageInParagraph() { - PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream(), new WriterProperties().AddUAXmpMetadata - ().SetPdfVersion(PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(DOG)); Document document = new Document(pdfDoc); Div div = new Div(); diff --git a/itext.tests/itext.pdfua.tests/itext/pdfua/checkers/PdfUATest.cs b/itext.tests/itext.pdfua.tests/itext/pdfua/checkers/PdfUATest.cs index 308ca75815..7d079a2d64 100644 --- a/itext.tests/itext.pdfua.tests/itext/pdfua/checkers/PdfUATest.cs +++ b/itext.tests/itext.pdfua.tests/itext/pdfua/checkers/PdfUATest.cs @@ -76,25 +76,6 @@ public virtual void InitializeFramework() { framework = new UaValidationTestFramework(DESTINATION_FOLDER); } - [NUnit.Framework.Test] - public virtual void FlushingOnPageWarningDisabledDoesntLog() { - String outPdf = DESTINATION_FOLDER + "flushingOnPageCloseLogsWarningDisabledTest.pdf"; - String cmpPdf = SOURCE_FOLDER + "cmp_flushingOnPageCloseLogsWarningDisabledTest.pdf"; - PdfUATestPdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(outPdf)); - pdfDoc.DisablePageFlushingWarning(); - Document document = new Document(pdfDoc); - PdfFont font = PdfFontFactory.CreateFont(FONT, PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED - ); - document.SetFont(font); - for (int i = 0; i < 40; i++) { - document.Add(new Paragraph("Hello World!")); - } - pdfDoc.GetPage(1).Flush(); - pdfDoc.Close(); - NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outPdf, cmpPdf, DESTINATION_FOLDER, "diff_" - )); - } - [NUnit.Framework.Test] public virtual void CheckPoint01_007_suspectsHasEntryTrue() { PdfUATestPdfDocument pdfDoc = new PdfUATestPdfDocument(new PdfWriter(new MemoryStream())); @@ -155,8 +136,8 @@ public virtual void InvalidUA1DocumentWithFlushedPageTest() { [NUnit.Framework.Test] public virtual void DocumentWithNoLangEntryTest() { String outPdf = DESTINATION_FOLDER + "documentWithNoLangEntryTest.pdf"; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddUAXmpMetadata().SetPdfVersion - (PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddPdfUaXmpMetadata(PdfUAConformance + .PDF_UA_1).SetPdfVersion(PdfVersion.PDF_1_7))); pdfDoc.SetTagged(); ValidationContainer validationContainer = new ValidationContainer(); validationContainer.AddChecker(new PdfUA1Checker(pdfDoc)); @@ -172,8 +153,8 @@ public virtual void DocumentWithNoLangEntryTest() { [NUnit.Framework.Test] public virtual void DocumentWithEmptyStringLangEntryTest() { String outPdf = DESTINATION_FOLDER + "documentWithEmptyStringLangEntryTest.pdf"; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddUAXmpMetadata().SetPdfVersion - (PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddPdfUaXmpMetadata(PdfUAConformance + .PDF_UA_1).SetPdfVersion(PdfVersion.PDF_1_7))); pdfDoc.SetTagged(); ValidationContainer validationContainer = new ValidationContainer(); validationContainer.AddChecker(new PdfUA1Checker(pdfDoc)); @@ -190,16 +171,8 @@ public virtual void DocumentWithEmptyStringLangEntryTest() { [NUnit.Framework.Test] public virtual void DocumentWithComplexLangEntryTest() { String outPdf = DESTINATION_FOLDER + "documentWithComplexLangEntryTest.pdf"; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddUAXmpMetadata().SetPdfVersion - (PdfVersion.PDF_1_7))); - pdfDoc.SetTagged(); - ValidationContainer validationContainer = new ValidationContainer(); - validationContainer.AddChecker(new PdfUA1Checker(pdfDoc)); - pdfDoc.GetDiContainer().Register(typeof(ValidationContainer), validationContainer); - pdfDoc.GetCatalog().SetLang(new PdfString("qaa-Qaaa-QM-x-southern")); - pdfDoc.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true)); - PdfDocumentInfo info = pdfDoc.GetDocumentInfo(); - info.SetTitle("English pangram"); + PdfDocument pdfDoc = new PdfUADocument(new PdfWriter(outPdf), new PdfUAConfig(PdfUAConformance.PDF_UA_1, "English pangram" + , "qaa-Qaaa-QM-x-southern")); pdfDoc.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outPdf, SOURCE_FOLDER + "cmp_documentWithComplexLangEntryTest.pdf" , DESTINATION_FOLDER, "diff_")); @@ -210,8 +183,8 @@ public virtual void DocumentWithComplexLangEntryTest() { [NUnit.Framework.Test] public virtual void DocumentWithoutViewerPreferencesTest() { String outPdf = DESTINATION_FOLDER + "documentWithoutViewerPreferencesTest.pdf"; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddUAXmpMetadata().SetPdfVersion - (PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddPdfUaXmpMetadata(PdfUAConformance + .PDF_UA_1).SetPdfVersion(PdfVersion.PDF_1_7))); pdfDoc.SetTagged(); ValidationContainer validationContainer = new ValidationContainer(); validationContainer.AddChecker(new PdfUA1Checker(pdfDoc)); @@ -226,8 +199,8 @@ public virtual void DocumentWithoutViewerPreferencesTest() { [NUnit.Framework.Test] public virtual void DocumentWithEmptyViewerPreferencesTest() { String outPdf = DESTINATION_FOLDER + "documentWithEmptyViewerPreferencesTest.pdf"; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddUAXmpMetadata().SetPdfVersion - (PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddPdfUaXmpMetadata(PdfUAConformance + .PDF_UA_1).SetPdfVersion(PdfVersion.PDF_1_7))); pdfDoc.SetTagged(); ValidationContainer validationContainer = new ValidationContainer(); validationContainer.AddChecker(new PdfUA1Checker(pdfDoc)); @@ -243,8 +216,8 @@ public virtual void DocumentWithEmptyViewerPreferencesTest() { [NUnit.Framework.Test] public virtual void DocumentWithInvalidViewerPreferencesTest() { String outPdf = DESTINATION_FOLDER + "documentWithEmptyViewerPreferencesTest.pdf"; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddUAXmpMetadata().SetPdfVersion - (PdfVersion.PDF_1_7))); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddPdfUaXmpMetadata(PdfUAConformance + .PDF_UA_1).SetPdfVersion(PdfVersion.PDF_1_7))); pdfDoc.SetTagged(); ValidationContainer validationContainer = new ValidationContainer(); validationContainer.AddChecker(new PdfUA1Checker(pdfDoc)); @@ -413,8 +386,9 @@ public virtual void OpenDocumentWithDuplicatingIdInStructTree() { [NUnit.Framework.Test] public virtual void ManualPdfUaCreation() { String outPdf = DESTINATION_FOLDER + "manualPdfUaCreation.pdf"; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, new WriterProperties().AddUAXmpMetadata().SetPdfVersion - (PdfVersion.PDF_1_7))); + WriterProperties properties = new WriterProperties().AddPdfUaXmpMetadata(PdfUAConformance.PDF_UA_1).SetPdfVersion + (PdfVersion.PDF_1_7); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf, properties)); Document document = new Document(pdfDoc, PageSize.A4.Rotate()); //TAGGED PDF //Make document tagged diff --git a/itext.tests/itext.pdfua.tests/resources/itext/pdfua/certificates/sign.pem b/itext.tests/itext.pdfua.tests/resources/itext/pdfua/certificates/sign.pem deleted file mode 100644 index 279a03bc23..0000000000 --- a/itext.tests/itext.pdfua.tests/resources/itext/pdfua/certificates/sign.pem +++ /dev/null @@ -1,55 +0,0 @@ ------BEGIN ENCRYPTED PRIVATE KEY----- -MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQckJU/1QOCBdNhbzA -qt9eJQICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEG383GXg0NLIhlxe -6SJAomIEggTQ6QRSX1Gx8X6JbCGnQitDEtZmjCbz8zF9Uq/AtAvDE7kuR1cnOmpn -+ElbU379I66fwiiGxzZNAh84ZXrDLEHojBQYLZBQI85Z/Rwy0zFi8S1BkI1Hhc3O -SplWOlqoof9PRIJ+cYTRe63+R4own1oReKSGGjzOqkw+hhi8PI06RZssqzahkNUd -Ag/AGp5zdV361TlszYWGJGSTQuDqbiXshXedLLjq65dDDyWYe5DV4mV2nOM0LYVn -IsRv4qBISl6tGCLsd1LHWwz8k/uotzFb9DzyA0fh6sV7JR3eGB8geMrNhlrvkVWN -xsXdB3gwW/u2SSMRcO2STs8PNbcs+IeznFUb4nqNbthoTZb24UyI0kC+ltfhMiMv -qnnpen1JY0ITOGNKyBaUm6uvh8SPrMvESHGFD7aJDVa7bzI+P+mZ+Xj+mk7NFoeT -N6lBkBiivBZ1ZgaHJsFFF4nq+LN/NWbxM+BYKy5yK6YPstatKuIvHwyD3GnLEnfq -dbr54l+qaSKei616ArjUK3jVqElC5vHRh9Vdfvqbt+tDWkxV1EIyzwDzG9mpGRU0 -Sopi4NdyRXZ+OvaV2YN4iXUhkbrJ/FodlJnUSo4YUthK1jA0pCdvbbLu4tBqd9iH -z23nKmSfguTGao6vfPVPkusUr00L0S1s1yDvevHM2IXF3DxFOkdkgdVSUzGkLenJ -N1aGBs+Eq4FVK/WuuLeM4njcoULqaOGnZ9j4ntBZXdrLZa1gwrLGwiGmIBOll6fN -7Btoj/frPvPp9RJwqyYjjILMSI0g/y1mzGIa5ODW7Dac4Lux0byzRYlxSdRlN3vb -nStW/Y1CcyhsOeiNHnJhmH8refNti6U9RZbgRBq9WeEbVTOdHZEn9QN8wVxpVz2H -csEocPezL80gI8rdVRlLO+igI7HqUZZTZwv25s5rQFj9fOo9/35gR6GXcYdSfezn -W4j9Q9Cb7S042hrKC2Qkhaoz+m68Ic9eNEGTiHOYZ5aLkHX4K38Bqxq7+rgi6eao -lao6UpnLOurZF5Fm+LEqsfFx+zbIHGJFIb22Y6zy01c9pKiAi77TJxEVC6WCE0dS -j1ywvdT1i1oZzDYBWnqJ0fczddbsc1/5gcvsj4sCFuRhP1KBpsTO3h4cG8TS/vKw -0rhljSsLbYnlKsguneNg4bb7tw2n5rCxGSkXaLgrfpexoxh5rHIr9Bcd9uTBhojE -xykqIG3LevcAn3+hAdEdvcwF0Ck/v4r/xXD3+pGKHbDR/076KKjWe6uR/Il3pegi -6QU95NNyWDNOsolv8fogsJzdjhYVONQlpavHRSWT95Jkrli9k0sfyDCKNLX/+142 -plFVHH9RQJfcrHFmJV40p96oeGKfiC0TTix45lM2QM3tF7Im2ajzCBchacAJFktH -DtaYeMcMLiJBvmv5Cb9gEkyUJ1QyTQIe+XUaFkSz9dfvQMsghRgYcUpD4IGleeWQ -70A0miyvu+y1mZpLe7qGsBugN8pjkbnqfPv/B2+7LPYT3JabW0Q9OMbmktEG6cjM -zim5Vq3EiCgEkI+G4lmdVF0dHhweCQzd88RfWjLyrsh8NcFy15jxaHaxw9llrB0A -oIhX8e8RBiqW5xD2PtNl1spO2m2kpCjfOKD4TOnxU+/c8Cbd25DgtZs= ------END ENCRYPTED PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UEBhMCQkUx -DjAMBgNVBAoMBWlUZXh0MR4wHAYDVQQDDBVpVGV4dFRlc3RJbnRlcm1lZGlhdGUw -IBcNMjAwMTAxMDAwMDAwWhgPMjQwMDAxMDEwMDAwMDBaMDUxCzAJBgNVBAYTAkJF -MQ4wDAYDVQQKDAVpVGV4dDEWMBQGA1UEAwwNaVRleHRUZXN0TGVhZjCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBANAerFO5YC/19zwIJCq9eT6dXtnZ9CR6 -D1qvOYD4mmcSYaQDxbkSGGhvF80TEKuuo0HypEy0xzKLK+zcuE/+e4qAIMYrA6PR -XxaXmGa1SiVVidG55TWWgbGNwBQ3xwpEBwWWWuz/va8bvjcmVuRaJdI9dajCpct4 -Crk9kNH/ctV6aT2/4oJ58NYRsHBzBIfm7XDoId8PyKGeSPLS6HIn9hd7o0H80eOa -lovIv19HyoQ16IhkuJ8wNgbHsz67e9DfsSk6vyBCP7DL01jvfHyPMPFHRTqhwjh8 -waCAVkfENJaAJwgNFTpu3QadG1qHLp9DC7bvpyaDLNxvVqCrtn16dgECAwEAAaOC -AT4wggE6MB0GA1UdDgQWBBQKzNSfEJzjZP6eEsBg1ltKDz9n0jAfBgNVHSMEGDAW -gBTmJ/JV3iF82DReVKOaHPWXKCq9izAOBgNVHQ8BAf8EBAMCBeAwgZkGCCsGAQUF -BwEBBIGMMIGJMD0GCCsGAQUFBzABhjFodHRwOi8vdGVzdC5leGFtcGxlLmNvbS9l -eGFtcGxlLWNhL29jc3Avc2lnbi1vY3NwMEgGCCsGAQUFBzAChjxodHRwOi8vdGVz -dC5leGFtcGxlLmNvbS9leGFtcGxlLWNhL2NlcnRzL2ludGVybWVkaWF0ZS9jYS5j -cnQwTAYDVR0fBEUwQzBBoD+gPYY7aHR0cDovL3Rlc3QuZXhhbXBsZS5jb20vZXhh -bXBsZS1jYS9jcmxzL3NpZ24tY3JsL2xhdGVzdC5jcmwwDQYJKoZIhvcNAQELBQAD -ggEBAFacTDkc4o4eTYwrgfFb5elu66897UIGHAL1UlXfWUUW7csMkSYSj/Sl7Wuj -ueGRY0l00eExRBCZW4UdcjwCNsI/9wC8CRpM90vw3e8MjKvm5KeVza3HydkIk/YU -h5M+5J1AcqgSUw1RHvRXhMoZ2/tOahoLawc4hU/6Fd5l2sxxxh7Vu/Ls5cQkLd5N -PSpcpByOAzCUAOcAWcBLlzdH5tS5GN69B+oKYBPDJYaSpRSWfljLcVfhr0F2Nuyb -JmtSs8hoiKFv+faCcWRnYnCpKxStc/bkMXosoTW6RU51wD+v4KI0BxXwfIv5UT6G -GoBJOuvldIX6xGU3GbcCyQzm5VA= ------END CERTIFICATE----- diff --git a/itext.tests/itext.pdfua.tests/resources/itext/pdfua/certificates/signCertRsa01.p12 b/itext.tests/itext.pdfua.tests/resources/itext/pdfua/certificates/signCertRsa01.p12 deleted file mode 100644 index 1377f70493..0000000000 Binary files a/itext.tests/itext.pdfua.tests/resources/itext/pdfua/certificates/signCertRsa01.p12 and /dev/null differ diff --git a/itext.tests/itext.sign.tests/itext/signatures/PdfSignerUnitTest.cs b/itext.tests/itext.sign.tests/itext/signatures/PdfSignerUnitTest.cs index a19742df41..53dc4b25b0 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/PdfSignerUnitTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/PdfSignerUnitTest.cs @@ -260,8 +260,8 @@ public virtual void TempFileProvidedTest() { public virtual void InitPdfaDocumentTest() { PdfSigner signer = new PdfSigner(new PdfReader(new MemoryStream(CreateSimplePdfaDocument())), new ByteArrayOutputStream (), new StampingProperties()); - NUnit.Framework.Assert.AreEqual(PdfAConformance.PDF_A_1A, ((PdfAAgnosticPdfDocument)signer.GetDocument()). - GetConformance().GetAConformance()); + NUnit.Framework.Assert.AreEqual(PdfAConformance.PDF_A_1A, signer.GetDocument().GetConformance().GetAConformance + ()); } [NUnit.Framework.Test] diff --git a/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUASignerTest.cs b/itext.tests/itext.sign.tests/itext/signatures/PdfUASignerTest.cs similarity index 95% rename from itext.tests/itext.pdfua.tests/itext/pdfua/PdfUASignerTest.cs rename to itext.tests/itext.sign.tests/itext/signatures/PdfUASignerTest.cs index 5838e9945c..fc2dafda59 100644 --- a/itext.tests/itext.pdfua.tests/itext/pdfua/PdfUASignerTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/PdfUASignerTest.cs @@ -23,7 +23,9 @@ You should have received a copy of the GNU Affero General Public License using System; using System.IO; using Microsoft.Extensions.Logging; +using iText.Bouncycastleconnector; using iText.Commons; +using iText.Commons.Bouncycastle; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Utils; @@ -34,25 +36,29 @@ You should have received a copy of the GNU Affero General Public License using iText.Kernel.Font; using iText.Kernel.Geom; using iText.Kernel.Pdf; +using iText.Pdfua; using iText.Pdfua.Exceptions; -using iText.Signatures; +using iText.Signatures.Testutils; using iText.Test; using iText.Test.Pdfa; -namespace iText.Pdfua { +namespace iText.Signatures { // Android-Conversion-Skip-Line (TODO DEVSIX-7377 introduce pdf\a validation on Android) [NUnit.Framework.Category("IntegrationTest")] public class PdfUASignerTest : ExtendedITextTest { + private static readonly IBouncyCastleFactory BOUNCY_CASTLE_FACTORY = BouncyCastleFactoryCreator.GetFactory + (); + private static readonly String DESTINATION_FOLDER = NUnit.Framework.TestContext.CurrentContext.TestDirectory - + "/test/itext/pdfua/PdfUASignerTest/"; + + "/test/itext/signatures/PdfUASignerTest/"; private static readonly String FONT = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext - .CurrentContext.TestDirectory) + "/resources/itext/pdfua/font/FreeSans.ttf"; + .CurrentContext.TestDirectory) + "/resources/itext/signatures/font/FreeSans.ttf"; private static readonly ILogger logger = ITextLogManager.GetLogger(typeof(PdfUASignerTest)); public static readonly String CERTIFICATE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext - .CurrentContext.TestDirectory) + "/resources/itext/pdfua/certificates/"; + .CurrentContext.TestDirectory) + "/resources/itext/signatures/certs/"; private static readonly char[] PASSWORD = "testpassphrase".ToCharArray(); @@ -180,7 +186,7 @@ public virtual void NormalPdfSignerInvisibleSignatureWithoutTU() { // Android-Conversion-Skip-Line (TODO DEVSIX-7377 introduce pdf\a validation on Android) [NUnit.Framework.Test] public virtual void NormalPdfSignerVisibleSignatureWithoutFont() { - // TODO DEVSIX-8623 Spike: Get rid of PdfADocument, PdfUADocument, PdfAAgnosticDocument in favour of one PdfDocument + // TODO DEVSIX-8676 Enable keeping A and UA conformance in PdfSigner //This test should fail with the appropriate exception MemoryStream inPdf = GenerateSimplePdfUA1Document(); String outPdf = GenerateSignatureNormal(inPdf, "normalPdfSignerVisibleSignatureWithoutFont", (signer) => { @@ -218,7 +224,7 @@ public virtual void NormalPdfSignerVisibleSignatureWithFont() { // Android-Conversion-Skip-Line (TODO DEVSIX-7377 introduce pdf\a validation on Android) [NUnit.Framework.Test] public virtual void NormalPdfSignerVisibleSignatureWithFontEmptyTU() { - // TODO DEVSIX-8623 Spike: Get rid of PdfADocument, PdfUADocument, PdfAAgnosticDocument in favour of one PdfDocument + // TODO DEVSIX-8676 Enable keeping A and UA conformance in PdfSigner //Should throw the correct exception if the font is not set MemoryStream inPdf = GenerateSimplePdfUA1Document(); PdfFont font = PdfFontFactory.CreateFont(FONT); @@ -312,8 +318,8 @@ public PdfUaSigner(PdfReader reader, Stream outputStream, String path, StampingP : base(reader, outputStream, path, properties) { } - protected override PdfDocument InitDocument(PdfReader reader, PdfWriter writer, StampingProperties properties - ) { + protected internal override PdfDocument InitDocument(PdfReader reader, PdfWriter writer, StampingProperties + properties) { return new PdfUADocument(reader, writer, new PdfUAConfig(PdfUAConformance.PDF_UA_1, "Title", "en-US")); } } diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/SignatureValidatorIntegrationTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/SignatureValidatorIntegrationTest.cs index dd3d1bec17..4720a7400c 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/SignatureValidatorIntegrationTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/SignatureValidatorIntegrationTest.cs @@ -22,11 +22,14 @@ You should have received a copy of the GNU Affero General Public License */ using System; using System.Collections.Generic; +using NUnit.Framework; using iText.Bouncycastleconnector; using iText.Commons.Bouncycastle; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; using iText.Commons.Utils; +using iText.Kernel.Crypto; +using iText.Kernel.Logs; using iText.Kernel.Pdf; using iText.Signatures; using iText.Signatures.Testutils; @@ -36,6 +39,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Signatures.Validation.Mocks; using iText.Signatures.Validation.Report; using iText.Test; +using iText.Test.Attributes; namespace iText.Signatures.Validation { [NUnit.Framework.Category("BouncyCastleIntegrationTest")] @@ -87,6 +91,58 @@ public virtual void ValidLatestSignatureTest() { ((al) => al.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(OCSPValidator.OCSP_RESPONDER_IS_CA))); } + [NUnit.Framework.Test] + [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] + public virtual void ValidateSignatureInEncryptedDocumentTest() { + String chainName = CERTS_SRC + "signCertRsa01.pem"; + IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName); + IX509Certificate rootCert = (IX509Certificate)certificateChain[1]; + ValidationReport report; + using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "encryptedDoc.pdf", new ReaderProperties + ().SetPassword("123".GetBytes(iText.Commons.Utils.EncodingUtil.ISO_8859_1))))) { + SignatureValidator signatureValidator = builder.BuildSignatureValidator(document); + report = signatureValidator.ValidateSignatures(); + } + NUnit.Framework.Assert.AreEqual(2, report.GetFailures().Count); + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE + ).HasLogItem((al) => al.WithCertificate(rootCert).WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK + ).WithMessage(CertificateChainValidator.ISSUER_MISSING, (i) => rootCert.GetSubjectDN())).HasLogItem((al + ) => al.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator + .NO_REVOCATION_DATA)).HasLogItem((al) => al.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK + ).WithMessage(RevocationDataValidator.SELF_SIGNED_CERTIFICATE))); + } + + [NUnit.Framework.Test] + [LogMessage(KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT, Ignore = true)] + public virtual void ValidateSignatureInEncryptedPubKeyDocumentTest() { + try { + BouncyCastleFactoryCreator.GetFactory().IsEncryptionFeatureSupported(0, true); + } + catch (Exception) { + NUnit.Framework.Assume.That(false); + } + String chainName = CERTS_SRC + "signCertRsa01.pem"; + IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName); + IX509Certificate rootCert = (IX509Certificate)certificateChain[1]; + ValidationReport report; + IX509Certificate certificate = CryptoUtil.ReadPublicCertificate(FileUtil.GetInputStreamForFile(CERTS_SRC + + "SHA256withRSA.cer")); + IPrivateKey privateKey = PemFileHelper.ReadFirstKey(CERTS_SRC + "SHA256withRSA.key", PASSWORD); + ReaderProperties properties = new ReaderProperties().SetPublicKeySecurityParams(certificate, privateKey); + using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "encryptedPublicKeyDocTest.pdf" + , properties))) { + SignatureValidator signatureValidator = builder.BuildSignatureValidator(document); + report = signatureValidator.ValidateSignatures(); + } + NUnit.Framework.Assert.AreEqual(2, report.GetFailures().Count); + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE + ).HasLogItem((al) => al.WithCertificate(rootCert).WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK + ).WithMessage(CertificateChainValidator.ISSUER_MISSING, (i) => rootCert.GetSubjectDN())).HasLogItem((al + ) => al.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator + .NO_REVOCATION_DATA)).HasLogItem((al) => al.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK + ).WithMessage(RevocationDataValidator.SELF_SIGNED_CERTIFICATE))); + } + [NUnit.Framework.Test] public virtual void ShortValidityCertsWithOcspTest() { String rootCertName = CERTS_SRC + "short_validity_root_cert.pem"; diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/certs/SHA256withRSA.cer b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/certs/SHA256withRSA.cer new file mode 100644 index 0000000000..fbaad2b382 Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/certs/SHA256withRSA.cer differ diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/certs/SHA256withRSA.key b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/certs/SHA256withRSA.key new file mode 100644 index 0000000000..d7e9b5e825 --- /dev/null +++ b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/certs/SHA256withRSA.key @@ -0,0 +1,51 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQdOaEUfD0sZWtUR11 +xwgn0gICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEBaNXSfwUjF5SS7n +ce1JFoUEggTQ6eV+IsckiVP7I9VTldLkpP5OKB8brmw5t20fO11HyCnqkkhooR2b +t2fBj4fWv0IRUe266L+fVs7AOngjkWfezEvGR6nte4pNXEFrOwt/U8A6IYZXBdA5 +dvqs6VMPHbjQ8CufVLGvksuYFQVRcGy0rk1DH2Of44GU4X0GtROlFFJnkmfZhVPS +Hx2MXXGQ02Ko1i1eKoEGgvmSAsDcPijiX96DKlQZJ4YMtI/8rRsdvNJsJ2beyZDa +T3aJMmSSBF92mS2dtS21DwjzEu8utquguYA0KYzjZM9onOuBEEUifam8Fjnvlui6 +beQJya4zldoA6QZPSd2PUAP6l1U/d8UXqcisjzArDZDmRu58dPxn4rs0NgTOIO8h +fEUIvfS+wuknff1b/wdGnwXkXoeSrrjS9dhP9KVU1SJ/FWKc6BY+P+JmE5vLjAtn +AmbyZhXY0jX7ZHFh0z0y1y1fTIXL1aj4iB+cUwhJ1ZdlGkT5HdG4ts/oTGCnpB6O +F1GvGyhprmtjp/dspLH5ha0I+4aTn46yFpnBNyg8w9c2+xj8Jiqy9J/ppVtPdhxt +wrE1/ThUGIWUTsbGbLW87WIrZq6IlSGtztbxAMYxXoe4solYueE3pI3eYFzgnBcq +T6Byktr71gt9AGD/N/p+Kk5RM4JT8XpQjLjz9TlmsGpJzUoBGeG6KFLsqqLLSD+0 +c5lAGWsFhec3uCu4fCyBqxpQc0y5j2bgUiTRGYn1NOdyZg+ERO/aWGfkDOAtlL1i +B79NGIBxIXgt508g83UeaQC6KjuG/8hPY6UHmU5mlgRT9H5jvkSX3mEtl1Gdk2y0 +M5pZTTrhbG4p66GhBi8vM5tQfiBoLUKEM/kgiGXPC6Kob42nb3ufP0rmnKklcDGC ++898hW5ge+VNmOkHpVuV5ZD9aWUSVEU4+8QNZj8pcyL0GXFyEL/HxNxUESdz3k0S +bInuxO49mgGPjBqtx5ZvaxyWFnzOp6rmHZUHymejxxdnlnTnSnXKkJFjcm7n0sKO +575ofHtk0OdqIK6YiPgfeF6nZkIg3C0PbReZ05kTplrW182ZWuQQyJgv+RPzF4+9 +5rCe67nJhJrt7hXFRsUScHXNj+HF9Av8WR2RnHTRbpQBJszijM+Xgl+VeYcY5ckB +fk+AfcR9r0Jud4O9795OOWVxWqGVu/b1RGonfjMkGW+JdnZL0vkOYYcHt4iMZmzW +M0ZowZPGO5dFBV7/ZkVzb0fexw+f+E0lUBEK1cx0gxnzjmcGJO+C9if1uIEfwpon +3wBOTDsU7XKDx9v6ibcDMOXrZa+rcJWxgNkXt5nRpozZkddYctBkehGu+snV2g4n +SdOwr0eIVv/L+v4IywZmeWWEVnbSAvB0p7nB89bgLMr9tV0ly7MWxPH+gPnNJ1gE +7Mp3AgN5BxEmLfW3+ou3QLoqnOS2MCw/xcgLP0nJACSPI7/nWy95iKXKgkCkAgF9 +4Ztk7uBG4tiK14KcKq8ToCW2YNliT3g0CWjBLtVPUS6qboudMiuedxTxE8WEirpT +A77nfDNg4MVjl4kP9jhV0Phpn9rDMJ2jw0BqFc1Vou4aNDXYandAFJea44Wce9H+ +qAowcrfsWehD01HBQ2KwWVg3sLnwwBHw0nvbATS41hdxsP2OmCnxWkc= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDfzCCAmegAwIBAgIEUFic9zANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJU +UzETMBEGA1UECBMKVGVzdCBTdGF0ZTESMBAGA1UEBxMJVGVzdCBUb3duMREwDwYD +VQQKEwhUZXN0IG9yZzEQMA4GA1UECxMHVGVzdCBPVTESMBAGA1UEAxMJVGVzdCBV +c2VyMCAXDTE0MDkyMjA5MTExMVoYDzIxMTQwODI5MDkxMTExWjBvMQswCQYDVQQG +EwJUUzETMBEGA1UECBMKVGVzdCBTdGF0ZTESMBAGA1UEBxMJVGVzdCBUb3duMREw +DwYDVQQKEwhUZXN0IG9yZzEQMA4GA1UECxMHVGVzdCBPVTESMBAGA1UEAxMJVGVz +dCBVc2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+6g5sYzXiNOA +hR7C8wc8buxU/JgcbdHpHIR44iuXjpepBYAE7hRsWM7H4cuXrKiRxS9UMOadqkGF +Qqb5sG6lo2UUhcj4qlN6hKDc/+AMZMIW1mvQldiygCAkqgM8iso+kw56dpVuerG/ +k1nd8f+X9rjXN6/DIMznZcMy2d9ByIFuixFKElPvOWx9q9N4aiueOd5FM5eHxp+3 +F4uCTrpM5zkS7Rmf5GVtCofc8KgaTLLp4D0Ge5VUJm7yW8fuU3eIpin4ivjk+Gye +Q3t0BsrmNyQy3CmKGOBP/vX0+wEMvGN2xqNgAFP9dxA+AbJMiAfsmoWvxXaPktqC +DOspTCFqbwIDAQABoyEwHzAdBgNVHQ4EFgQUILviRCmSrhuLDmF0nus4pv2uu7gw +DQYJKoZIhvcNAQELBQADggEBAGnfGYL7nDm5taDPRxuGGMqUPwRnH2bXwef6S2Xb +/nIEFtNheVFQFtKNn5Ikq68DTFMP06yXLnI7F40+ZiQezRBB1EPPmDL2fYKc9fL1 +SHntu6HLgP/Y5nnCVegtL8l9745gQZnnXlMtkTs2HFwffznIHW/3STO0Bcj0+KMa +p8vebMjmvV7bZEGvrcrVXL55QPZXJwRuQMXJB3f5XhAEH1VqAhTW6DrvBUnuESwo +9fxxA5gmblt80SQYdKr2I08OTk0qmyF8zNuffTOiSS8/V6Cf7CntuPWjSuVf1EVP +MH6KkSjceLZ99Y7bvl7KKvQ4Kj5Bp27PwlRvtYbfCUmQEG8= +-----END CERTIFICATE----- diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/certs/signCertRsa01.pem b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/certs/signCertRsa01.pem new file mode 100644 index 0000000000..5f2f1f25a8 --- /dev/null +++ b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/certs/signCertRsa01.pem @@ -0,0 +1,76 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQgLsVp4wmljjCRgEy +kw2LWgICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEELyxbQ1T8vAMXX6t +md0GgdwEggTQXjePuN2mrJ4C7uFP/ErLys5cwO7QSOL5z7jUUep96YkZgMjau99o +6JolOHyJRzDbUNbTCfku8PqwDfdPrCPfMZ+e9UU/Y5uVZbEL+UtIkcH/uyFCd1k7 +AVOhAux7KZwgHlq66iUHqTQFd58Ly7KOoMKGZS07CtIxjYluFZZbx44EZrgqRwEa +ZAbIsdR2xZ092Who4CzkuF31m2TuyzfYir7kocJsdQU6k9OdptfJRda2UpZiUXW8 +GMg/qvF7RwkAbfu7gLkcmc5FETlY+E3P8tYDutN737wnd/VqO9Bd25umOAl3CHUA +5+YSXvWOSuAJjz7kEI2DEG/ov//oO0wohJPLKRF7jUI2WbIwCAypPZPvSS506ulO +ofuLTY0+Jii0ZO5SyC4Uu90lh8RISvi9RzRx2G4sN+gyeCBBg1R1f5IRNeBImpEw +aKqk4VrcUrLe623Z3el1Z8ErJBJ6G0ZV/EAFC7dmpTknrVOFzdO6sohtnHygm0Ce +h5QdqiWvb0QKHv3GZumdtCcdh8vPMRT1PEWVvfV/cyIOc5BH6sYNtxiohosl6DLz +I84vj3n8I+cFHrYIFCtghy9iZJ0GvvPxaiJCS5A+eDiOO3rhk3ZMkmTlVCpOBiY2 +QKdljhmRaN1Y6XfQ8SRNmr/qVfwFJ4JgYnk3VVHVvzt0EvEImNusOvTH2U4zMryP +FRhgGNIL0f5gflo2LxSPqsnqNfJLRHCmXkYeB4Pu8/xv6biFqtwC2UBaL7FCjIgY +NI+hi9Mt9fJpYqF4XGHcT2b6Aq7otgxX+5iiQg10bEjqI/gcZrFvBvmz/97OBe7X +BFa5F8nYeSxnr5XQiJ04oBVBjdvAFeS7ZZ4Quq2beEgcgCj7EU/OXLLHwBCCmD8s +8kgkhsv7+sPtNnC1YeoW6xHezt/FSDYxS1lPWsnr4AE4jpxOJgM8CNSDq0E52e83 +2uDNm3gIo133RRn9V8gNQzfIJv1BZFRUtOn9CRxrJBTptSxUJX1at+btTM7hlY2z +MwXM5i7ZGDVQOPSpKrlbmA8bHDRHeGryXz0HNWs5RWiTVSEhCuVTrrlQG4nmbhVm +b6xbd/DWs3NdEXwLLdg1W+fbeS2qIJtJqu0LU+PcGkhaVXeobc6MFGw06hDVtVg9 +Hm1/AZJ4OuD/+GyH9ku4Z9tPDh4NmXsVVV8CpzxRJ37gLrGPwbxXwW3v6B6NBRvz +W8KuWQjlNDxVcFb9Si7Mj81xX2k1818hwSm3iEQIwT0Q7BNUj3oJhTsNlB/Id79J +tl7AKam1ofDZVmU7gPcv0FPKxhEZIyjoqeAzLGuW1Hmp45HbJ94tL2uvbgPq2Mj7 +j4jllaPoN9J1QBVDHBqEzLZGeWKZYK2L9Sw4SdkZjLp96hxoQ7MYvTrsX4eSV0HH +xMLp5hhIiM8zGIsMYlwcfOSpQh/H1AnbiQIJ0/tzO6uBZ73fq59rTReRf+PtXqqT +5vg89nN6kNvJcrwNLyEhdC7uaqsoimTMi59BE36ZZcL0jHKMmPl9g/vbPj9CiRdu +B0+4lQD0hAqK6FVfl6ENpj4zLdU6/EER5L7v+Syv8d5AeFtdKrqxH3oCGPXmXCol +j2rALoIlZt0D+jjmcDo6C32qtu8w40zBD/+J8iZXVWC/U9cauP00N9E= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIID6TCCAtGgAwIBAgIEWOew7DANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJC +WTEOMAwGA1UEBwwFTWluc2sxDjAMBgNVBAoMBWlUZXh0MQ0wCwYDVQQLDAR0ZXN0 +MRYwFAYDVQQDDA1pVGV4dFRlc3RSb290MCAXDTE3MDQwNzE1MzM0MFoYDzIxMTcw +NDA3MTUzMzQwWjBZMQswCQYDVQQGEwJCWTEOMAwGA1UEBwwFTWluc2sxDjAMBgNV +BAoMBWlUZXh0MQ0wCwYDVQQLDAR0ZXN0MRswGQYDVQQDDBJpVGV4dFRlc3RSc2FD +ZXJ0MDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCfr2PnZ6DjvrSY +g0cWtDR6drgvCowB5hQH7CHSAMTeVGZxUOBT1ylfxySioRU4ckq3uQu7jOe7Te6Y +xEenjFhTv8bT0/ZrL2w6OGBH4iUs3Kwx5jzbRHPuZt7+gCKLBXhRH6ytDnbTHNgT +4tjGXUmGa4sMbal1mXvKN/xaK+hGDskRW6cHZq7ZtdgfM8yBQWZzshAz7dQepmUH +ZYWxplTwJ8cuVLqjgXMXWfTatio6yYwf+5AkWszBcCA6oxm16wN2pLUeNx5aBLiF +Dhtj6qqHLwN/7tPb0ojqXRU3AfocC2y8a4WeVOOp2du0ja4E9P7IQNKiBBlOfNcF +D700qPFpAgMBAAGjgbswgbgwCQYDVR0TBAIwADB/BgNVHSMEeDB2gBRdKnF1rt3Y +vlm6ILFmkcl2NlNc7qFYpFYwVDELMAkGA1UEBhMCQlkxDjAMBgNVBAcMBU1pbnNr +MQ4wDAYDVQQKDAVpVGV4dDENMAsGA1UECwwEdGVzdDEWMBQGA1UEAwwNaVRleHRU +ZXN0Um9vdIIEWOeR1jAdBgNVHQ4EFgQUz41Jo8H/HAqxhMN/inuhKuLZU8gwCwYD +VR0PBAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IBAQCT597xhkVzrYP7NudRgIZCDwT3 +TDnL+Xv8H4c9p+CdHJtFMoxAQlzcQi4uEIo5nfBKMEXK0d1OnO8zEBfK98EPahUI +++PDnNk82kh64CbZQ95Ms1Usq1XGd31bkXWWRM3LY2P7VG0nR+eLutVAClIcbTLN +yL9ZhiL33jCk1W5PeXJy13kL3XV/Awt8zb9fcinkuXkV5LoZHxh2Ob19R//5fGxH +hnUywReGptnIbEPiWGYyX1QCQeOqi3vmqZaGr+RZfF8+zqtSP5p4gFpryuTJxkcZ +UOeroaBv3sHCI9rtzcwZPYsW0BroFliEhNIDq5HxJgdwdu6uDOMMrC2QxB17 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIEWOeR1jANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJC +WTEOMAwGA1UEBwwFTWluc2sxDjAMBgNVBAoMBWlUZXh0MQ0wCwYDVQQLDAR0ZXN0 +MRYwFAYDVQQDDA1pVGV4dFRlc3RSb290MCAXDTE3MDQwNzEzMjAwMVoYDzIxMTcw +NDA3MTMyMDAxWjBUMQswCQYDVQQGEwJCWTEOMAwGA1UEBwwFTWluc2sxDjAMBgNV +BAoMBWlUZXh0MQ0wCwYDVQQLDAR0ZXN0MRYwFAYDVQQDDA1pVGV4dFRlc3RSb290 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz/fz7iq1wzhMMYcGfmMm +teCY/ZtdE26PB1OTTBuDSN86sVNmur5FV/mLPU9ZK2ofrs+wMrqn0agmFlRl4dTh +f5u5WSEQ/ARwXzYOn2uEkwR/0dwwZUL3VWhrPSD5SxX5MzFo8UXTNlXW2bClLC0F +QU2qLjIwwRFwwWDSQPR8r/Mv181RljVpEjPk6DfkDtHWWA4daGlQU0nXbuZszplv +iPafXmyKn+2w4G9Jw/8pHIK2VhWYstLI+bUZk662ZVldNvnpMyHn12FfB0Nbf/Z6 +V2WTGviEr8EEE2cA7I+H7ZGUDzug7umNCCJn3ilC6vAt9i9OLaZRDh6jPMOjMUiz +TwIDAQABo4HBMIG+MA8GA1UdEwEB/wQFMAMBAf8wfwYDVR0jBHgwdoAUXSpxda7d +2L5ZuiCxZpHJdjZTXO6hWKRWMFQxCzAJBgNVBAYTAkJZMQ4wDAYDVQQHDAVNaW5z +azEOMAwGA1UECgwFaVRleHQxDTALBgNVBAsMBHRlc3QxFjAUBgNVBAMMDWlUZXh0 +VGVzdFJvb3SCBFjnkdYwHQYDVR0OBBYEFF0qcXWu3di+WbogsWaRyXY2U1zuMAsG +A1UdDwQEAwIB9jANBgkqhkiG9w0BAQsFAAOCAQEAdhby6EaopoUF8j7oR44Mhe/N +3y9hzGb/zLmmgTavPd2plv6NlAPt9W+8rezKO6jQCsBRFw8JY+Lx6j3W0K6rWigB +pPGU/B/0bXLlOIv2a4uW8nBmq6jxAe5Xbtwm8HcKOOLMzxPIChHJIJy5NWw9ArD4 +Ul+FEt/VuEW1NfPZm1U5ixMOrBfn0C8pxIX4+VSHN9I8WoFjSfYX4Y3ldRLTeqxQ +rhZQlbhGNymp3Kcvtuq5At6vopskyB8Q1b7L4e+hRWK2prz/7p4Bdhu2TmkEfWZc +YKpgrkVFqa/Z1uZ0q4KVBOP3cyaQmqRXTV37SfpNyHAJdol5ueF68VVVNZFRXw== +-----END CERTIFICATE----- diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/encryptedDoc.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/encryptedDoc.pdf new file mode 100644 index 0000000000..e4563ea8d0 Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/encryptedDoc.pdf differ diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/encryptedPublicKeyDocTest.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/encryptedPublicKeyDocTest.pdf new file mode 100644 index 0000000000..929f7454d5 Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/SignatureValidatorIntegrationTest/encryptedPublicKeyDocTest.pdf differ diff --git a/itext/itext.kernel/itext/kernel/logs/KernelLogMessageConstant.cs b/itext/itext.kernel/itext/kernel/logs/KernelLogMessageConstant.cs index 78dee1ca36..b5f35fe1c1 100644 --- a/itext/itext.kernel/itext/kernel/logs/KernelLogMessageConstant.cs +++ b/itext/itext.kernel/itext/kernel/logs/KernelLogMessageConstant.cs @@ -98,6 +98,8 @@ public sealed class KernelLogMessageConstant { public const String ALGORITHM_NOT_FROM_SPEC = "Requested algorithm might not be supported by the pdf specification."; + public const String MEMORYLIMITAWAREHANDLER_OVERRIDE_CREATENEWINSTANCE_METHOD = "MemoryLimitsAwareHandler#createNewInstance method must be overriden."; + private KernelLogMessageConstant() { } //Private constructor will prevent the instantiation of this class directly diff --git a/itext/itext.kernel/itext/kernel/pdf/DefaultFontStrategy.cs b/itext/itext.kernel/itext/kernel/pdf/DefaultFontStrategy.cs new file mode 100644 index 0000000000..0eda7a38e7 --- /dev/null +++ b/itext/itext.kernel/itext/kernel/pdf/DefaultFontStrategy.cs @@ -0,0 +1,75 @@ +/* +This file is part of the iText (R) project. +Copyright (c) 1998-2024 Apryse Group NV +Authors: Apryse Software. + +This program is offered under a commercial and under the AGPL license. +For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. + +AGPL licensing: +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +using Microsoft.Extensions.Logging; +using iText.Commons; +using iText.Kernel.Font; + +namespace iText.Kernel.Pdf { + /// + /// The class defines a default font strategy for + /// + /// which is used in the scope of + /// . + /// + public class DefaultFontStrategy { + private readonly PdfDocument pdfDocument; + + private PdfFont defaultFont = null; + + /// + /// Instantiates a new instance of + /// + /// which + /// will be used for passed + /// + /// instance. + /// + /// the pdf document for which the strategy will be used to + public DefaultFontStrategy(PdfDocument pdfDocument) { + this.pdfDocument = pdfDocument; + } + + /// Gets default font. + /// + /// the + /// + /// instance + /// + public virtual PdfFont GetFont() { + if (defaultFont == null) { + try { + defaultFont = PdfFontFactory.CreateFont(); + if (pdfDocument.GetWriter() != null) { + defaultFont.MakeIndirect(pdfDocument); + } + } + catch (System.IO.IOException e) { + ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.DefaultFontStrategy)); + logger.LogError(e, iText.IO.Logs.IoLogMessageConstant.EXCEPTION_WHILE_CREATING_DEFAULT_FONT); + defaultFont = null; + } + } + return defaultFont; + } + } +} diff --git a/itext/itext.kernel/itext/kernel/pdf/DocumentInfoHelper.cs b/itext/itext.kernel/itext/kernel/pdf/DocumentInfoHelper.cs new file mode 100644 index 0000000000..a1d5c30de5 --- /dev/null +++ b/itext/itext.kernel/itext/kernel/pdf/DocumentInfoHelper.cs @@ -0,0 +1,55 @@ +/* +This file is part of the iText (R) project. +Copyright (c) 1998-2024 Apryse Group NV +Authors: Apryse Software. + +This program is offered under a commercial and under the AGPL license. +For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. + +AGPL licensing: +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +namespace iText.Kernel.Pdf { + /// + /// The class is helper which used inside + /// + /// to properly configure PDF document's info dictionary. + /// + public class DocumentInfoHelper { + /// If document info dictionary should be added to the trailer. + /// + /// + /// + /// if should be added, otherwise + /// + /// + public virtual bool ShouldAddDocumentInfoToTrailer() { + return true; + } + + /// + /// Adjusts document info before it's flushing and adding to the trailer + /// if required, see + /// . + /// + /// + /// the + /// + /// instance to adjust + /// + public virtual void AdjustDocumentInfo(PdfDocumentInfo documentInfo) { + } + // do nothing + } +} diff --git a/itext/itext.kernel/itext/kernel/pdf/MemoryLimitsAwareHandler.cs b/itext/itext.kernel/itext/kernel/pdf/MemoryLimitsAwareHandler.cs index b59b59cb0c..c78afdd828 100644 --- a/itext/itext.kernel/itext/kernel/pdf/MemoryLimitsAwareHandler.cs +++ b/itext/itext.kernel/itext/kernel/pdf/MemoryLimitsAwareHandler.cs @@ -22,7 +22,10 @@ You should have received a copy of the GNU Affero General Public License */ using System; using System.Collections.Generic; +using Microsoft.Extensions.Logging; +using iText.Commons; using iText.Kernel.Exceptions; +using iText.Kernel.Logs; namespace iText.Kernel.Pdf { /// @@ -43,6 +46,9 @@ namespace iText.Kernel.Pdf { /// /// public class MemoryLimitsAwareHandler { + private static readonly ILogger LOGGER = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.MemoryLimitsAwareHandler + )); + private const int SINGLE_SCALE_COEFFICIENT = 100; private const int SUM_SCALE_COEFFICIENT = 500; @@ -115,6 +121,29 @@ private MemoryLimitsAwareHandler(int maxSizeOfSingleDecompressedPdfStream, long this.maxXObjectsSizePerPage = maxXObjectsSizePerPage; } + /// + /// Creates a new instance of + /// + /// by copying settings from this instance + /// of + /// . + /// + /// + /// a new instance of + /// . + /// + public virtual iText.Kernel.Pdf.MemoryLimitsAwareHandler CreateNewInstance() { + iText.Kernel.Pdf.MemoryLimitsAwareHandler to = new iText.Kernel.Pdf.MemoryLimitsAwareHandler(); + to.maxSizeOfSingleDecompressedPdfStream = this.maxSizeOfSingleDecompressedPdfStream; + to.maxSizeOfDecompressedPdfStreamsSum = this.maxSizeOfDecompressedPdfStreamsSum; + to.maxNumberOfElementsInXrefStructure = this.maxNumberOfElementsInXrefStructure; + to.maxXObjectsSizePerPage = this.maxXObjectsSizePerPage; + if (this.GetType() != typeof(iText.Kernel.Pdf.MemoryLimitsAwareHandler)) { + LOGGER.LogWarning(KernelLogMessageConstant.MEMORYLIMITAWAREHANDLER_OVERRIDE_CREATENEWINSTANCE_METHOD); + } + return to; + } + /// Gets the maximum allowed size which can be occupied by a single decompressed pdf stream. /// the maximum allowed size which can be occupied by a single decompressed pdf stream. public virtual int GetMaxSizeOfSingleDecompressedPdfStream() { diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfConformance.cs b/itext/itext.kernel/itext/kernel/pdf/PdfConformance.cs index 5c7bc1a192..524ea7bd5b 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfConformance.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfConformance.cs @@ -22,6 +22,7 @@ You should have received a copy of the GNU Affero General Public License */ using System; using iText.Kernel.XMP; +using iText.Kernel.XMP.Options; using iText.Kernel.XMP.Properties; namespace iText.Kernel.Pdf { @@ -239,6 +240,40 @@ public static iText.Kernel.Pdf.PdfConformance GetConformance(XMPMeta meta) { return new iText.Kernel.Pdf.PdfConformance(aLevel, uaLevel); } + /// Sets required fields into XMP metadata according to passed PDF conformance. + /// the xmp metadata to which required PDF conformance fields will be set + /// the PDF conformance according to which XMP will be updated + public static void SetConformanceToXmp(XMPMeta xmpMeta, iText.Kernel.Pdf.PdfConformance conformance) { + if (conformance == null) { + return; + } + // Don't set any property if property value was set, so if + // smth was invalid in source document, it will be left as is. + // But if e.g. for PDF/A-4 revision wasn't specified, we will fix it. + if (conformance.IsPdfUA()) { + if (xmpMeta.GetProperty(XMPConst.NS_PDFUA_ID, XMPConst.PART) == null) { + xmpMeta.SetPropertyInteger(XMPConst.NS_PDFUA_ID, XMPConst.PART, 1, new PropertyOptions(PropertyOptions.SEPARATE_NODE + )); + } + } + if (conformance.IsPdfA()) { + PdfAConformance aLevel = conformance.GetAConformance(); + if (xmpMeta.GetProperty(XMPConst.NS_PDFA_ID, XMPConst.PART) == null) { + xmpMeta.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.PART, aLevel.GetPart()); + } + if (aLevel.GetLevel() != null && xmpMeta.GetProperty(XMPConst.NS_PDFA_ID, XMPConst.CONFORMANCE) == null) { + xmpMeta.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.CONFORMANCE, aLevel.GetLevel()); + } + if ("4".Equals(aLevel.GetPart()) && xmpMeta.GetProperty(XMPConst.NS_PDFA_ID, XMPConst.REV) == null) { + xmpMeta.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.REV, iText.Kernel.Pdf.PdfConformance.PDF_A_4_REVISION); + } + if (xmpMeta.GetPropertyInteger(XMPConst.NS_PDFUA_ID, XMPConst.PART) != null) { + XMPMeta taggedExtensionMeta = XMPMetaFactory.ParseFromString(PDF_UA_EXTENSION); + XMPUtils.AppendProperties(taggedExtensionMeta, xmpMeta, true, false); + } + } + } + /// /// Gets an instance of /// @@ -316,5 +351,23 @@ private static PdfUAConformance GetUAConformance(String part) { } return null; } + + private const String PDF_UA_EXTENSION = " \n" + " \n" + + " \n" + + " \n" + " \n" + " \n" + + " \n" + + " pdfuaid\n" + " PDF/UA identification schema\n" + + " \n" + " \n" + " \n" + + " internal\n" + " PDF/UA version identifier\n" + + " part\n" + " Integer\n" + + " \n" + " \n" + " internal\n" + + " PDF/UA amendment identifier\n" + + " amd\n" + " Text\n" + + " \n" + " \n" + " internal\n" + + " PDF/UA corrigenda identifier\n" + + " corr\n" + " Text\n" + + " \n" + " \n" + " \n" + + " \n" + " \n" + " \n" + + " \n" + " \n" + " "; } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfDocument.cs b/itext/itext.kernel/itext/kernel/pdf/PdfDocument.cs index af293ebf9d..eec61fff30 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfDocument.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfDocument.cs @@ -58,7 +58,7 @@ public class PdfDocument : IDisposable { , PdfName.Size, PdfName.Prev, PdfName.Root, PdfName.Info, PdfName.ID, PdfName.XRefStm, PdfName.AuthCode }; - private static readonly IPdfPageFactory pdfPageFactory = new PdfPageFactory(); + private static readonly ILogger LOGGER = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); protected internal readonly StampingProperties properties; @@ -106,6 +106,8 @@ public class PdfDocument : IDisposable { /// Document version. protected internal PdfVersion pdfVersion = PdfVersion.PDF_1_7; + protected internal PdfConformance pdfConformance = PdfConformance.PDF_NONE_CONFORMANCE; + protected internal FingerPrint fingerPrint; protected internal SerializeOptions serializeOptions = new SerializeOptions(); @@ -127,6 +129,12 @@ public class PdfDocument : IDisposable { protected internal TagStructureContext tagStructureContext; + protected internal DocumentInfoHelper documentInfoHelper = new DocumentInfoHelper(); + + protected internal DefaultFontStrategy defaultFontStrategy; + + protected internal IPdfPageFactory pdfPageFactory = new PdfPageFactory(); + //\cond DO_NOT_DOCUMENT /// Cache of already serialized objects from this document for smart mode. internal IDictionary serializedObjectsCache = new DictionaryThe original modified (second) id when the document is read initially. private PdfString modifiedDocumentId; - private PdfFont defaultFont = null; - private EncryptedEmbeddedStreamsHandler encryptedEmbeddedStreamsHandler; /// Document info. @@ -170,12 +176,14 @@ public class PdfDocument : IDisposable { /// PDF reader. public PdfDocument(PdfReader reader) : this(reader, new DocumentProperties()) { + defaultFontStrategy = new DefaultFontStrategy(this); } /// Open PDF document in reading mode. /// PDF reader. /// document properties public PdfDocument(PdfReader reader, DocumentProperties properties) { + defaultFontStrategy = new DefaultFontStrategy(this); if (reader == null) { throw new ArgumentException("The reader in PdfDocument constructor can not be null."); } @@ -193,6 +201,7 @@ public PdfDocument(PdfReader reader, DocumentProperties properties) { /// PDF writer public PdfDocument(PdfWriter writer) : this(writer, new DocumentProperties()) { + defaultFontStrategy = new DefaultFontStrategy(this); } /// Open PDF document in writing mode. @@ -203,6 +212,7 @@ public PdfDocument(PdfWriter writer) /// PDF writer /// document properties public PdfDocument(PdfWriter writer, DocumentProperties properties) { + defaultFontStrategy = new DefaultFontStrategy(this); if (writer == null) { throw new ArgumentException("The writer in PdfDocument constructor can not be null."); } @@ -221,6 +231,7 @@ public PdfDocument(PdfWriter writer, DocumentProperties properties) { /// PDF writer. public PdfDocument(PdfReader reader, PdfWriter writer) : this(reader, writer, new StampingProperties()) { + defaultFontStrategy = new DefaultFontStrategy(this); } /// Open PDF document in stamping mode. @@ -228,6 +239,7 @@ public PdfDocument(PdfReader reader, PdfWriter writer) /// PDF writer. /// properties of the stamping process public PdfDocument(PdfReader reader, PdfWriter writer, StampingProperties properties) { + defaultFontStrategy = new DefaultFontStrategy(this); if (reader == null) { throw new ArgumentException("The reader in PdfDocument constructor can not be null."); } @@ -240,16 +252,25 @@ public PdfDocument(PdfReader reader, PdfWriter writer, StampingProperties proper this.properties = properties; bool writerHasEncryption = WriterHasEncryption(); if (properties.appendMode && writerHasEncryption) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogWarning(iText.IO.Logs.IoLogMessageConstant.WRITER_ENCRYPTION_IS_IGNORED_APPEND); + LOGGER.LogWarning(iText.IO.Logs.IoLogMessageConstant.WRITER_ENCRYPTION_IS_IGNORED_APPEND); } if (properties.preserveEncryption && writerHasEncryption) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogWarning(iText.IO.Logs.IoLogMessageConstant.WRITER_ENCRYPTION_IS_IGNORED_PRESERVE); + LOGGER.LogWarning(iText.IO.Logs.IoLogMessageConstant.WRITER_ENCRYPTION_IS_IGNORED_PRESERVE); } Open(writer.properties.pdfVersion); } + /// Checks if the document closing has been started or not. + /// + /// + /// + /// if closing process has been started, otherwise + /// + /// + public virtual bool IsClosing() { + return isClosing; + } + /// Sets the XMP Metadata. /// /// Sets the XMP Metadata. @@ -294,8 +315,7 @@ protected internal virtual void SetXmpMetadata(byte[] xmpMetadata) { GetXmpMetadata(); } catch (XMPException e) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogError(e, iText.IO.Logs.IoLogMessageConstant.EXCEPTION_WHILE_UPDATING_XMPMETADATA); + LOGGER.LogError(e, iText.IO.Logs.IoLogMessageConstant.EXCEPTION_WHILE_UPDATING_XMPMETADATA); } } @@ -373,7 +393,6 @@ public virtual byte[] GetXmpMetadataBytes(bool createNew) { XMPMeta xmpMeta = XMPMetaFactory.Create(); xmpMeta.SetObjectName(XMPConst.TAG_XMPMETA); xmpMeta.SetObjectName(""); - AddCustomMetadataExtensions(xmpMeta); try { xmpMeta.SetProperty(XMPConst.NS_DC, PdfConst.Format, "application/pdf"); SetXmpMetadata(xmpMeta); @@ -904,6 +923,14 @@ public virtual void Close() { } PdfObject crypto = null; ICollection forbiddenToFlush = new HashSet(); + documentInfoHelper.AdjustDocumentInfo(GetDocumentInfo()); + // The following 2 operators prevent the possible inconsistency between root and info + // entries existing in the trailer object and corresponding fields. This inconsistency + // may appear when user gets trailer and explicitly sets new root or info dictionaries. + if (documentInfoHelper.ShouldAddDocumentInfoToTrailer()) { + trailer.Put(PdfName.Info, GetDocumentInfo().GetPdfObject()); + } + trailer.Put(PdfName.Root, catalog.GetPdfObject()); if (properties.appendMode) { if (structTreeRoot != null) { TryFlushTagStructure(true); @@ -921,11 +948,13 @@ public virtual void Close() { } } PdfObject pageRoot = catalog.GetPageTree().GenerateTree(); - FlushInfoDictionary(properties.appendMode); if (catalog.GetPdfObject().IsModified() || pageRoot.IsModified()) { catalog.Put(PdfName.Pages, pageRoot); catalog.GetPdfObject().Flush(false); } + if (GetDocumentInfo().GetPdfObject().IsModified()) { + GetDocumentInfo().GetPdfObject().Flush(false); + } FlushFonts(); if (writer.crypto != null) { System.Diagnostics.Debug.Assert(reader.decrypt.GetPdfObject() == writer.crypto.GetPdfObject(), "Conflict with source encryption" @@ -969,8 +998,8 @@ public virtual void Close() { if (structTreeRoot != null) { TryFlushTagStructure(false); } - FlushInfoDictionary(properties.appendMode); catalog.GetPdfObject().Flush(false); + GetDocumentInfo().GetPdfObject().Flush(false); FlushFonts(); if (writer.crypto != null) { crypto = writer.crypto.GetPdfObject(); @@ -1001,10 +1030,6 @@ public virtual void Close() { // no need to flush crypto in append mode, it shall not have changed in this case crypto.Flush(false); } - // The following operator prevents the possible inconsistency between root and info - // entries existing in the trailer object and corresponding fields. This inconsistency - // may appear when user gets trailer and explicitly sets new root or info dictionaries. - trailer.Put(PdfName.Root, catalog.GetPdfObject()); //By this time original and modified document ids should always be not null due to initializing in // either writer properties, or in the writer init section on document open or from pdfreader. So we // shouldn't worry about it being null next @@ -1034,8 +1059,7 @@ public virtual void Close() { writer.Finish(); } catch (Exception e) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogError(e, iText.IO.Logs.IoLogMessageConstant.PDF_WRITER_CLOSING_FAILED); + LOGGER.LogError(e, iText.IO.Logs.IoLogMessageConstant.PDF_WRITER_CLOSING_FAILED); } } if (reader != null && IsCloseReader()) { @@ -1043,8 +1067,7 @@ public virtual void Close() { reader.Close(); } catch (Exception e) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogError(e, iText.IO.Logs.IoLogMessageConstant.PDF_READER_CLOSING_FAILED); + LOGGER.LogError(e, iText.IO.Logs.IoLogMessageConstant.PDF_READER_CLOSING_FAILED); } } } @@ -1163,7 +1186,7 @@ public virtual IList CopyPagesTo(int pageFrom, int pageTo, iText.Kernel /// /// the document conformance public virtual PdfConformance GetConformance() { - return reader == null ? PdfConformance.PDF_NONE_CONFORMANCE : reader.GetPdfConformance(); + return pdfConformance; } /// @@ -1399,8 +1422,7 @@ public virtual IList CopyPagesTo(IList pagesToCopy, iText.Kernel.P } } else { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogWarning(iText.IO.Logs.IoLogMessageConstant.NOT_TAGGED_PAGES_IN_TAGGED_DOCUMENT); + LOGGER.LogWarning(iText.IO.Logs.IoLogMessageConstant.NOT_TAGGED_PAGES_IN_TAGGED_DOCUMENT); } } if (catalog.IsOutlineMode()) { @@ -1623,8 +1645,7 @@ public virtual void AddNamedDestination(String key, PdfObject value) { public virtual void AddNamedDestination(PdfString key, PdfObject value) { CheckClosingStatus(); if (value.IsArray() && ((PdfArray)value).Get(0).IsNumber()) { - ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)).LogWarning(iText.IO.Logs.IoLogMessageConstant - .INVALID_DESTINATION_TYPE); + LOGGER.LogWarning(iText.IO.Logs.IoLogMessageConstant.INVALID_DESTINATION_TYPE); } catalog.AddNamedDestination(key, value); } @@ -1715,8 +1736,7 @@ public virtual void AddFileAttachment(String key, PdfFileSpec fs) { /// public virtual void AddAssociatedFile(String description, PdfFileSpec fs) { if (null == ((PdfDictionary)fs.GetPdfObject()).Get(PdfName.AFRelationship)) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogError(iText.IO.Logs.IoLogMessageConstant.ASSOCIATED_FILE_SPEC_SHALL_INCLUDE_AFRELATIONSHIP); + LOGGER.LogError(iText.IO.Logs.IoLogMessageConstant.ASSOCIATED_FILE_SPEC_SHALL_INCLUDE_AFRELATIONSHIP); } PdfArray afArray = catalog.GetPdfObject().GetAsArray(PdfName.AF); if (afArray == null) { @@ -1766,7 +1786,7 @@ public virtual PdfEncryptedPayloadDocument GetEncryptedPayloadDocument() { } } catch (PdfException e) { - ITextLogManager.GetLogger(GetType()).LogError(e.Message); + LOGGER.LogError(e.Message); } } } @@ -1793,7 +1813,7 @@ public virtual void SetEncryptedPayload(PdfFileSpec fs) { throw new PdfException(KernelExceptionMessageConstant.CANNOT_SET_ENCRYPTED_PAYLOAD_TO_ENCRYPTED_DOCUMENT); } if (!PdfName.EncryptedPayload.Equals(((PdfDictionary)fs.GetPdfObject()).Get(PdfName.AFRelationship))) { - ITextLogManager.GetLogger(GetType()).LogError(iText.IO.Logs.IoLogMessageConstant.ENCRYPTED_PAYLOAD_FILE_SPEC_SHALL_HAVE_AFRELATIONSHIP_FILED_EQUAL_TO_ENCRYPTED_PAYLOAD + LOGGER.LogError(iText.IO.Logs.IoLogMessageConstant.ENCRYPTED_PAYLOAD_FILE_SPEC_SHALL_HAVE_AFRELATIONSHIP_FILED_EQUAL_TO_ENCRYPTED_PAYLOAD ); } PdfEncryptedPayload encryptedPayload = PdfEncryptedPayload.ExtractFrom(fs); @@ -1803,7 +1823,7 @@ public virtual void SetEncryptedPayload(PdfFileSpec fs) { } PdfCollection collection = GetCatalog().GetCollection(); if (collection != null) { - ITextLogManager.GetLogger(GetType()).LogWarning(iText.IO.Logs.IoLogMessageConstant.COLLECTION_DICTIONARY_ALREADY_EXISTS_IT_WILL_BE_MODIFIED + LOGGER.LogWarning(iText.IO.Logs.IoLogMessageConstant.COLLECTION_DICTIONARY_ALREADY_EXISTS_IT_WILL_BE_MODIFIED ); } else { @@ -1963,20 +1983,7 @@ public virtual PdfFont GetFont(PdfDictionary dictionary) { /// on error. /// public virtual PdfFont GetDefaultFont() { - if (defaultFont == null) { - try { - defaultFont = PdfFontFactory.CreateFont(); - if (writer != null) { - defaultFont.MakeIndirect(this); - } - } - catch (System.IO.IOException e) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogError(e, iText.IO.Logs.IoLogMessageConstant.EXCEPTION_WHILE_CREATING_DEFAULT_FONT); - defaultFont = null; - } - } - return defaultFont; + return defaultFontStrategy.GetFont(); } /// @@ -2091,22 +2098,25 @@ protected internal virtual void StoreDestinationToReaddress(PdfDestination desti )); } - /// - /// Mark an object with - /// . - /// - /// an object to mark. - protected internal virtual void MarkObjectAsMustBeFlushed(PdfObject pdfObject) { - if (pdfObject.GetIndirectReference() != null) { - pdfObject.GetIndirectReference().SetState(PdfObject.MUST_BE_FLUSHED); - } - } - /// Flush an object. /// object to flush. /// indicates whether object can be placed into object stream. protected internal virtual void FlushObject(PdfObject pdfObject, bool canBeInObjStm) { - writer.FlushObject(pdfObject, canBeInObjStm); + bool flushAllowed = true; + if (!isClosing && this.GetDiContainer().IsRegistered(typeof(ValidationContainer))) { + ValidationContainer container = this.GetDiContainer().GetInstance(); + if (container != null) { + flushAllowed = container.IsPdfObjectChecked(pdfObject); + } + } + if (isClosing || flushAllowed) { + writer.FlushObject(pdfObject, canBeInObjStm); + } + else { + if (pdfObject.GetIndirectReference() != null) { + pdfObject.GetIndirectReference().SetState(PdfObject.MUST_BE_FLUSHED); + } + } } /// Initializes document. @@ -2162,9 +2172,14 @@ protected internal virtual void Open(PdfVersion newPdfVersion) { throw new PdfException(KernelExceptionMessageConstant.APPEND_MODE_REQUIRES_A_DOCUMENT_WITHOUT_ERRORS_EVEN_IF_RECOVERY_IS_POSSIBLE ); } + pdfConformance = reader.GetPdfConformance(); } xref.InitFreeReferencesList(this); if (writer != null) { + if (writer.properties.addPdfAXmpMetadata != null || writer.properties.addPdfUaXmpMetadata != null) { + pdfConformance = new PdfConformance(writer.properties.addPdfAXmpMetadata, writer.properties.addPdfUaXmpMetadata + ); + } EnableByteArrayWritingMode(); if (reader != null && reader.HasXrefStm() && writer.properties.isFullCompression == null) { writer.properties.isFullCompression = true; @@ -2288,29 +2303,6 @@ protected internal virtual void Open(PdfVersion newPdfVersion) { } } - /// Adds custom XMP metadata extension. - /// Adds custom XMP metadata extension. Useful for PDF/UA, ZUGFeRD, etc. - /// - /// - /// - /// to add custom metadata to. - /// - protected internal virtual void AddCustomMetadataExtensions(XMPMeta xmpMeta) { - } - - /// Flush info dictionary if needed. - /// true if the document is edited in append mode. - protected internal virtual void FlushInfoDictionary(bool appendMode) { - PdfObject infoDictObj = GetDocumentInfo().GetPdfObject(); - if (!appendMode || infoDictObj.IsModified()) { - infoDictObj.Flush(false); - } - // The following operator prevents the possible inconsistency between root and info - // entries existing in the trailer object and corresponding fields. This inconsistency - // may appear when user gets trailer and explicitly sets new root or info dictionaries. - trailer.Put(PdfName.Info, infoDictObj); - } - /// Updates XMP metadata. /// /// Updates XMP metadata. @@ -2322,12 +2314,12 @@ protected internal virtual void UpdateXmpMetadata() { // in the info dictionary. if (GetXmpMetadataBytes() != null || writer.properties.addXmpMetadata || pdfVersion.CompareTo(PdfVersion.PDF_2_0 ) >= 0) { - SetXmpMetadata(UpdateDefaultXmpMetadata()); + XMPMeta xmpMeta = UpdateDefaultXmpMetadata(); + SetXmpMetadata(xmpMeta); } } catch (XMPException e) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogError(e, iText.IO.Logs.IoLogMessageConstant.EXCEPTION_WHILE_UPDATING_XMPMETADATA); + LOGGER.LogError(e, iText.IO.Logs.IoLogMessageConstant.EXCEPTION_WHILE_UPDATING_XMPMETADATA); } } @@ -2339,11 +2331,7 @@ protected internal virtual void UpdateXmpMetadata() { protected internal virtual XMPMeta UpdateDefaultXmpMetadata() { XMPMeta xmpMeta = GetXmpMetadata(true); XmpMetaInfoConverter.AppendDocumentInfoToMetadata(GetDocumentInfo(), xmpMeta); - if (IsTagged() && writer.properties.addUAXmpMetadata && xmpMeta.GetProperty(XMPConst.NS_PDFUA_ID, XMPConst - .PART) == null) { - xmpMeta.SetPropertyInteger(XMPConst.NS_PDFUA_ID, XMPConst.PART, 1, new PropertyOptions(PropertyOptions.SEPARATE_NODE - )); - } + PdfConformance.SetConformanceToXmp(xmpMeta, pdfConformance); return xmpMeta; } @@ -2446,8 +2434,7 @@ protected internal virtual void TryInitTagStructure(PdfDictionary str) { catch (Exception e) { structTreeRoot = null; structParentIndex = -1; - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogError(e, iText.IO.Logs.IoLogMessageConstant.TAG_STRUCTURE_INIT_FAILED); + LOGGER.LogError(e, iText.IO.Logs.IoLogMessageConstant.TAG_STRUCTURE_INIT_FAILED); } } @@ -2668,8 +2655,7 @@ private void ReadDocumentIds() { private void ProcessReadingError(String errorMessage) { if (PdfReader.StrictnessLevel.CONSERVATIVE.IsStricter(reader.GetStrictnessLevel())) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogError(errorMessage); + LOGGER.LogError(errorMessage); } else { throw new PdfException(errorMessage); @@ -2679,13 +2665,11 @@ private void ProcessReadingError(String errorMessage) { private static void OverrideFullCompressionInWriterProperties(WriterProperties properties, bool readerHasXrefStream ) { if (true == properties.isFullCompression && !readerHasXrefStream) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogWarning(KernelLogMessageConstant.FULL_COMPRESSION_APPEND_MODE_XREF_TABLE_INCONSISTENCY); + LOGGER.LogWarning(KernelLogMessageConstant.FULL_COMPRESSION_APPEND_MODE_XREF_TABLE_INCONSISTENCY); } else { if (false == properties.isFullCompression && readerHasXrefStream) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); - logger.LogWarning(KernelLogMessageConstant.FULL_COMPRESSION_APPEND_MODE_XREF_STREAM_INCONSISTENCY); + LOGGER.LogWarning(KernelLogMessageConstant.FULL_COMPRESSION_APPEND_MODE_XREF_STREAM_INCONSISTENCY); } } properties.isFullCompression = readerHasXrefStream; diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfReader.cs b/itext/itext.kernel/itext/kernel/pdf/PdfReader.cs index 1ef28ebff2..6a364a79c6 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfReader.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfReader.cs @@ -770,6 +770,22 @@ public virtual bool IsEncrypted() { return encrypted; } + /// + /// Gets a copy of + /// + /// used to create this instance of + /// . + /// + /// + /// a copy of + /// + /// used to create this instance of + /// + /// + public virtual ReaderProperties GetPropertiesCopy() { + return new ReaderProperties(properties); + } + /// Parses the entire PDF protected internal virtual void ReadPdf() { String version = tokens.CheckPdfHeader(); diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfRevisionsReader.cs b/itext/itext.kernel/itext/kernel/pdf/PdfRevisionsReader.cs index 73fdedabcf..320e3de431 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfRevisionsReader.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfRevisionsReader.cs @@ -74,7 +74,7 @@ public virtual IList GetAllRevisions() { RandomAccessFileOrArray raf = reader.GetSafeFile(); WindowRandomAccessSource source = new WindowRandomAccessSource(raf.CreateSourceView(), 0, raf.Length()); using (Stream inputStream = new RASInputStream(source)) { - using (PdfReader newReader = new PdfReader(inputStream)) { + using (PdfReader newReader = new PdfReader(inputStream, reader.GetPropertiesCopy())) { using (PdfDocument newDocument = new PdfDocument(newReader, new DocumentProperties().SetEventCountingMetaInfo (metaInfo))) { newDocument.GetXref().UnmarkReadingCompleted(); diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfWriter.cs b/itext/itext.kernel/itext/kernel/pdf/PdfWriter.cs index d24c1b40d3..d4c5ae5529 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfWriter.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfWriter.cs @@ -149,6 +149,12 @@ public virtual iText.Kernel.Pdf.PdfWriter SetCompressionLevel(int compressionLev return this; } + /// Gets defined pdf version for the document. + /// version for the document + public virtual PdfVersion GetPdfVersion() { + return properties.pdfVersion; + } + /// Gets the writer properties. /// /// The diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfXrefTable.cs b/itext/itext.kernel/itext/kernel/pdf/PdfXrefTable.cs index 2f8bf818cf..db481d0c72 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfXrefTable.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfXrefTable.cs @@ -282,7 +282,9 @@ protected internal virtual void WriteXrefTableAndTrailer(PdfDocument document, P int offsetSize = GetOffsetSize(Math.Max(startxref, Size())); xrefStream.Put(PdfName.W, new PdfArray(JavaUtil.ArraysAsList((PdfObject)new PdfNumber(1), new PdfNumber(offsetSize ), new PdfNumber(2)))); - xrefStream.Put(PdfName.Info, document.GetDocumentInfo().GetPdfObject()); + if (document.GetTrailer().Get(PdfName.Info) != null) { + xrefStream.Put(PdfName.Info, document.GetTrailer().Get(PdfName.Info)); + } xrefStream.Put(PdfName.Root, document.GetCatalog().GetPdfObject()); PdfArray index = new PdfArray(); foreach (int? section in sections) { diff --git a/itext/itext.kernel/itext/kernel/pdf/ReaderProperties.cs b/itext/itext.kernel/itext/kernel/pdf/ReaderProperties.cs index 80490c493a..5a81800442 100644 --- a/itext/itext.kernel/itext/kernel/pdf/ReaderProperties.cs +++ b/itext/itext.kernel/itext/kernel/pdf/ReaderProperties.cs @@ -22,21 +22,38 @@ You should have received a copy of the GNU Affero General Public License */ using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; +using iText.Commons.Utils; namespace iText.Kernel.Pdf { + /// The class representing various properties used to read PDF documents. public class ReaderProperties { - //added by ujihara for decryption protected internal byte[] password; - //added by Aiken Sam for certificate decryption protected internal IPrivateKey certificateKey; - //added by Aiken Sam for certificate decryption protected internal IX509Certificate certificate; - //added by Aiken Sam for certificate decryption protected internal MemoryLimitsAwareHandler memoryLimitsAwareHandler; + /// + /// Creates an instance of + /// . + /// + public ReaderProperties() { + } + +//\cond DO_NOT_DOCUMENT + // Empty constructor + internal ReaderProperties(iText.Kernel.Pdf.ReaderProperties readerProperties) { + this.password = readerProperties.password == null ? null : JavaUtil.ArraysCopyOf(readerProperties.password + , readerProperties.password.Length); + this.certificateKey = readerProperties.certificateKey; + this.certificate = readerProperties.certificate; + this.memoryLimitsAwareHandler = readerProperties.memoryLimitsAwareHandler == null ? null : readerProperties + .memoryLimitsAwareHandler.CreateNewInstance(); + } +//\endcond + /// Defines the password which will be used if the document is encrypted with standard encryption. /// /// Defines the password which will be used if the document is encrypted with standard encryption. @@ -48,7 +65,7 @@ public class ReaderProperties { /// /// instance /// - public virtual ReaderProperties SetPassword(byte[] password) { + public virtual iText.Kernel.Pdf.ReaderProperties SetPassword(byte[] password) { ClearEncryptionParams(); this.password = password; return this; @@ -74,8 +91,8 @@ public virtual ReaderProperties SetPassword(byte[] password) { /// /// instance /// - public virtual ReaderProperties SetPublicKeySecurityParams(IX509Certificate certificate, IPrivateKey certificateKey - ) { + public virtual iText.Kernel.Pdf.ReaderProperties SetPublicKeySecurityParams(IX509Certificate certificate, + IPrivateKey certificateKey) { ClearEncryptionParams(); this.certificate = certificate; this.certificateKey = certificateKey; @@ -97,18 +114,12 @@ public virtual ReaderProperties SetPublicKeySecurityParams(IX509Certificate cert /// /// instance /// - public virtual ReaderProperties SetPublicKeySecurityParams(IX509Certificate certificate) { + public virtual iText.Kernel.Pdf.ReaderProperties SetPublicKeySecurityParams(IX509Certificate certificate) { ClearEncryptionParams(); this.certificate = certificate; return this; } - private void ClearEncryptionParams() { - this.password = null; - this.certificate = null; - this.certificateKey = null; - } - /// Sets the memory handler which will be used to handle decompressed PDF streams. /// the memory handler which will be used to handle decompressed PDF streams /// @@ -117,10 +128,16 @@ private void ClearEncryptionParams() { /// /// instance /// - public virtual ReaderProperties SetMemoryLimitsAwareHandler(MemoryLimitsAwareHandler memoryLimitsAwareHandler + public virtual iText.Kernel.Pdf.ReaderProperties SetMemoryLimitsAwareHandler(MemoryLimitsAwareHandler memoryLimitsAwareHandler ) { this.memoryLimitsAwareHandler = memoryLimitsAwareHandler; return this; } + + private void ClearEncryptionParams() { + this.password = null; + this.certificate = null; + this.certificateKey = null; + } } } diff --git a/itext/itext.kernel/itext/kernel/pdf/WriterProperties.cs b/itext/itext.kernel/itext/kernel/pdf/WriterProperties.cs index 799183609e..a3f989fc02 100644 --- a/itext/itext.kernel/itext/kernel/pdf/WriterProperties.cs +++ b/itext/itext.kernel/itext/kernel/pdf/WriterProperties.cs @@ -40,7 +40,9 @@ public class WriterProperties { protected internal bool addXmpMetadata; - protected internal bool addUAXmpMetadata; + protected internal PdfAConformance addPdfAXmpMetadata = null; + + protected internal PdfUAConformance addPdfUaXmpMetadata = null; protected internal PdfVersion pdfVersion; @@ -54,7 +56,6 @@ public class WriterProperties { public WriterProperties() { smartMode = false; - addUAXmpMetadata = false; compressionLevel = CompressionConstants.DEFAULT_COMPRESSION; isFullCompression = null; encryptionProperties = new EncryptionProperties(); @@ -114,6 +115,54 @@ public virtual iText.Kernel.Pdf.WriterProperties AddXmpMetadata() { return this; } + /// Adds PDF/A XMP metadata to the PDF document. + /// + /// Adds PDF/A XMP metadata to the PDF document. + /// + /// This method calls + /// + /// implicitly. + /// + /// NOTE: Calling this method only affects the XMP metadata, but doesn't enable any additional checks that the + /// created document meets all PDF/A requirements. When using this method make sure you are familiar with PDF/A + /// document requirements. If you are not sure, use dedicated iText PDF/A module to create valid PDF/A documents. + /// + /// the PDF/A conformance which will be added to XMP metadata + /// + /// this + /// + /// instance + /// + public virtual iText.Kernel.Pdf.WriterProperties AddPdfAXmpMetadata(PdfAConformance aConformance) { + this.addPdfAXmpMetadata = aConformance; + AddXmpMetadata(); + return this; + } + + /// Adds PDF/UA XMP metadata to the PDF document. + /// + /// Adds PDF/UA XMP metadata to the PDF document. + /// + /// This method calls + /// + /// implicitly. + /// + /// NOTE: Calling this method only affects the XMP metadata, but doesn't enable any additional checks that the + /// created document meets all PDF/UA requirements. When using this method make sure you are familiar with PDF/UA + /// document requirements. If you are not sure, use dedicated iText PDF/UA module to create valid PDF/UA documents. + /// + /// the PDF/UA conformance which will be added to XMP metadata + /// + /// this + /// + /// instance + /// + public virtual iText.Kernel.Pdf.WriterProperties AddPdfUaXmpMetadata(PdfUAConformance uaConformance) { + this.addPdfUaXmpMetadata = uaConformance; + AddXmpMetadata(); + return this; + } + /// Defines the level of compression for the document. /// /// Defines the level of compression for the document. @@ -470,25 +519,6 @@ public virtual iText.Kernel.Pdf.WriterProperties SetModifiedDocumentId(PdfString return this; } - /// This method marks the document as PDF/UA and sets related flags is XMPMetaData. - /// - /// This method marks the document as PDF/UA and sets related flags is XMPMetaData. - /// This method calls - /// - /// implicitly. - /// NOTE: iText does not validate PDF/UA, which means we don't check if created PDF meets all PDF/UA requirements. - /// Don't use this method if you are not familiar with PDF/UA specification in order to avoid creation of non-conformant PDF/UA file. - /// - /// - /// this - /// - /// instance - /// - public virtual iText.Kernel.Pdf.WriterProperties AddUAXmpMetadata() { - this.addUAXmpMetadata = true; - return AddXmpMetadata(); - } - //\cond DO_NOT_DOCUMENT internal virtual bool IsStandardEncryptionUsed() { return encryptionProperties.IsStandardEncryptionUsed(); diff --git a/itext/itext.kernel/itext/kernel/validation/IValidationChecker.cs b/itext/itext.kernel/itext/kernel/validation/IValidationChecker.cs index 10feddfd9f..19c60b737e 100644 --- a/itext/itext.kernel/itext/kernel/validation/IValidationChecker.cs +++ b/itext/itext.kernel/itext/kernel/validation/IValidationChecker.cs @@ -20,6 +20,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ +using iText.Kernel.Pdf; + namespace iText.Kernel.Validation { /// Used to check if a PDF document is compliant to a specific validation profile. public interface IValidationChecker { @@ -33,5 +35,20 @@ public interface IValidationChecker { /// to validate /// void Validate(IValidationContext validationContext); + + /// + /// Is + /// + /// ready to flush. + /// + /// the pdf object to check + /// + /// + /// + /// if the object is ready to flush, + /// + /// otherwise + /// + bool IsPdfObjectReadyToFlush(PdfObject @object); } } diff --git a/itext/itext.kernel/itext/kernel/validation/ValidationContainer.cs b/itext/itext.kernel/itext/kernel/validation/ValidationContainer.cs index 58352c12df..7eb9c2ac1b 100644 --- a/itext/itext.kernel/itext/kernel/validation/ValidationContainer.cs +++ b/itext/itext.kernel/itext/kernel/validation/ValidationContainer.cs @@ -21,6 +21,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ using System.Collections.Generic; +using iText.Kernel.Pdf; namespace iText.Kernel.Validation { /// @@ -112,5 +113,29 @@ public virtual void AddChecker(IValidationChecker checker) { public virtual bool ContainsChecker(IValidationChecker checker) { return validationCheckers.Contains(checker); } + + /// + /// Is + /// + /// ready to flush according to all added + /// + /// implementations. + /// + /// the pdf object to check + /// + /// + /// + /// if the object is ready to flush, + /// + /// otherwise + /// + public virtual bool IsPdfObjectChecked(PdfObject pdfObject) { + foreach (IValidationChecker checker in validationCheckers) { + if (!checker.IsPdfObjectReadyToFlush(pdfObject)) { + return false; + } + } + return true; + } } } diff --git a/itext/itext.pdfa/itext/pdfa/PdfAAgnosticPdfDocument.cs b/itext/itext.pdfa/itext/pdfa/PdfAAgnosticPdfDocument.cs deleted file mode 100644 index 11a3794fb6..0000000000 --- a/itext/itext.pdfa/itext/pdfa/PdfAAgnosticPdfDocument.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* -This file is part of the iText (R) project. -Copyright (c) 1998-2024 Apryse Group NV -Authors: Apryse Software. - -This program is offered under a commercial and under the AGPL license. -For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. - -AGPL licensing: -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ -using iText.Kernel.Pdf; - -namespace iText.Pdfa { - /// - /// This class extends - /// - /// and serves as - /// - /// for - /// PDF/A compliant documents and as - /// - /// for non PDF/A documents. - /// - /// - /// This class extends - /// - /// and serves as - /// - /// for - /// PDF/A compliant documents and as - /// - /// for non PDF/A documents. - /// - /// This class can throw various exceptions like - /// - /// as well as - /// - /// for PDF/A documents. - /// - public class PdfAAgnosticPdfDocument : PdfADocument { - /// Opens a PDF/A document in stamping mode. - /// - /// the - /// - /// - /// - /// the - /// - /// object to write to - /// - public PdfAAgnosticPdfDocument(PdfReader reader, PdfWriter writer) - : this(reader, writer, new StampingProperties()) { - } - - /// Opens a PDF/A document in stamping mode. - /// - /// the - /// - /// - /// - /// the - /// - /// object to write to - /// - /// - /// - /// - /// of the stamping process - /// - public PdfAAgnosticPdfDocument(PdfReader reader, PdfWriter writer, StampingProperties properties) - : base(reader, writer, properties, true) { - } - } -} diff --git a/itext/itext.pdfa/itext/pdfa/PdfADefaultFontStrategy.cs b/itext/itext.pdfa/itext/pdfa/PdfADefaultFontStrategy.cs new file mode 100644 index 0000000000..3f3fb194c7 --- /dev/null +++ b/itext/itext.pdfa/itext/pdfa/PdfADefaultFontStrategy.cs @@ -0,0 +1,49 @@ +/* +This file is part of the iText (R) project. +Copyright (c) 1998-2024 Apryse Group NV +Authors: Apryse Software. + +This program is offered under a commercial and under the AGPL license. +For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. + +AGPL licensing: +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +using iText.Kernel.Font; +using iText.Kernel.Pdf; + +namespace iText.Pdfa { + /// + /// The class presents default font strategy for PDF/A documents which + /// doesn't provide default font because all used fonts must be embedded. + /// + public class PdfADefaultFontStrategy : DefaultFontStrategy { + /// + /// Instantiates a new + /// + /// instance based on the document which will use that strategy. + /// + /// the pdf document which will use that strategy + public PdfADefaultFontStrategy(PdfDocument pdfDocument) + : base(pdfDocument) { + } + + /// + /// . + /// + public override PdfFont GetFont() { + return null; + } + } +} diff --git a/itext/itext.pdfa/itext/pdfa/PdfADocument.cs b/itext/itext.pdfa/itext/pdfa/PdfADocument.cs index e8bc592baa..bfe63814dd 100644 --- a/itext/itext.pdfa/itext/pdfa/PdfADocument.cs +++ b/itext/itext.pdfa/itext/pdfa/PdfADocument.cs @@ -23,11 +23,9 @@ You should have received a copy of the GNU Affero General Public License using System; using Microsoft.Extensions.Logging; using iText.Commons; -using iText.Kernel.Font; +using iText.Commons.Utils; using iText.Kernel.Pdf; -using iText.Kernel.Pdf.Tagutils; using iText.Kernel.Validation; -using iText.Kernel.XMP; using iText.Pdfa.Checker; using iText.Pdfa.Exceptions; using iText.Pdfa.Logs; @@ -44,10 +42,12 @@ namespace iText.Pdfa { /// /// and is in charge of creating files /// that comply with the PDF/A standard. + /// /// Client code is still responsible for making sure the file is actually PDF/A /// compliant: multiple steps must be undertaken (depending on the /// /// ) to ensure that the PDF/A standard is followed. + /// /// This class will throw exceptions, mostly /// /// , @@ -56,16 +56,6 @@ namespace iText.Pdfa { /// . /// public class PdfADocument : PdfDocument { - private static readonly IPdfPageFactory pdfAPageFactory = new PdfAPageFactory(); - - protected internal PdfAChecker checker; - - private bool alreadyLoggedThatObjectFlushingWasNotPerformed = false; - - private bool alreadyLoggedThatPageFlushingWasNotPerformed = false; - - private PdfConformance conformance; - /// Constructs a new PdfADocument for writing purposes, i.e. from scratch. /// /// Constructs a new PdfADocument for writing purposes, i.e. from scratch. A @@ -108,24 +98,17 @@ public PdfADocument(PdfWriter writer, PdfAConformance aConformance, PdfOutputInt /// public PdfADocument(PdfWriter writer, PdfAConformance aConformance, PdfOutputIntent outputIntent, DocumentProperties properties) - : base(writer, properties) { - this.conformance = new PdfConformance(aConformance); - SetChecker(aConformance); + : base(ConfigureWriterProperties(writer, aConformance), properties) { + PdfAChecker checker = GetCorrectCheckerFromConformance(GetConformance().GetAConformance()); + ValidationContainer validationContainer = new ValidationContainer(); + validationContainer.AddChecker(checker); + GetDiContainer().Register(typeof(ValidationContainer), validationContainer); + this.pdfPageFactory = new PdfAPageFactory(checker); + this.documentInfoHelper = new PdfADocumentInfoHelper(this); + this.defaultFontStrategy = new PdfADefaultFontStrategy(this); AddOutputIntent(outputIntent); } - /// No default font for PDF/A documents. - /// - /// - /// . - /// - public override PdfFont GetDefaultFont() { - if (GetConformance().IsPdfA()) { - return null; - } - return base.GetDefaultFont(); - } - /// Opens a PDF/A document in the stamping mode. /// PDF reader. /// PDF writer. @@ -138,152 +121,28 @@ public PdfADocument(PdfReader reader, PdfWriter writer) /// PDF writer. /// properties of the stamping process public PdfADocument(PdfReader reader, PdfWriter writer, StampingProperties properties) - : this(reader, writer, properties, false) { - } - -//\cond DO_NOT_DOCUMENT - internal PdfADocument(PdfReader reader, PdfWriter writer, StampingProperties properties, bool tolerant) : base(reader, writer, properties) { - this.conformance = base.GetConformance(); - if (!GetConformance().IsPdfA() && !tolerant) { + if (!GetConformance().IsPdfA()) { throw new PdfAConformanceException(PdfaExceptionMessageConstant.DOCUMENT_TO_READ_FROM_SHALL_BE_A_PDFA_CONFORMANT_FILE_WITH_VALID_XMP_METADATA ); } - SetChecker(GetConformance().GetAConformance()); - } -//\endcond - - /// - /// - /// - /// - /// - public override void AddOutputIntent(PdfOutputIntent outputIntent) { - base.AddOutputIntent(outputIntent); - checker.SetPdfAOutputIntentColorSpace(GetCatalog().GetPdfObject()); - } - - public override PdfConformance GetConformance() { - return conformance; - } - -//\cond DO_NOT_DOCUMENT - internal virtual void LogThatPdfAPageFlushingWasNotPerformed() { - if (!alreadyLoggedThatPageFlushingWasNotPerformed) { - alreadyLoggedThatPageFlushingWasNotPerformed = true; - // This log message will be printed once for one instance of the document. - ITextLogManager.GetLogger(typeof(iText.Pdfa.PdfADocument)).LogWarning(PdfALogMessageConstant.PDFA_PAGE_FLUSHING_WAS_NOT_PERFORMED - ); - } - } -//\endcond - - protected override void AddCustomMetadataExtensions(XMPMeta xmpMeta) { - if (!GetConformance().IsPdfA()) { - base.AddCustomMetadataExtensions(xmpMeta); - return; - } - if (this.IsTagged()) { - try { - if (xmpMeta.GetPropertyInteger(XMPConst.NS_PDFUA_ID, XMPConst.PART) != null) { - XMPMeta taggedExtensionMeta = XMPMetaFactory.ParseFromString(PdfAXMPUtil.PDF_UA_EXTENSION); - XMPUtils.AppendProperties(taggedExtensionMeta, xmpMeta, true, false); - } - } - catch (XMPException exc) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Pdfa.PdfADocument)); - logger.LogError(exc, iText.IO.Logs.IoLogMessageConstant.EXCEPTION_WHILE_UPDATING_XMPMETADATA); - } - } - } - - protected override void UpdateXmpMetadata() { - if (!GetConformance().IsPdfA()) { - base.UpdateXmpMetadata(); - return; - } - try { - XMPMeta xmpMeta = UpdateDefaultXmpMetadata(); - PdfAConformance aLevel = checker.GetAConformance(); - xmpMeta.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.PART, aLevel.GetPart()); - if (aLevel.GetLevel() != null) { - xmpMeta.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.CONFORMANCE, aLevel.GetLevel()); - } - if ("4".Equals(aLevel.GetPart())) { - xmpMeta.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.REV, PdfConformance.PDF_A_4_REVISION); - } - AddCustomMetadataExtensions(xmpMeta); - SetXmpMetadata(xmpMeta); - } - catch (XMPException e) { - ILogger logger = ITextLogManager.GetLogger(typeof(iText.Pdfa.PdfADocument)); - logger.LogError(e, iText.IO.Logs.IoLogMessageConstant.EXCEPTION_WHILE_UPDATING_XMPMETADATA); - } - } - - public override void CheckIsoConformance(IValidationContext validationContext) { - SetCheckerIfChanged(); - base.CheckIsoConformance(validationContext); - } - - protected override void FlushObject(PdfObject pdfObject, bool canBeInObjStm) { - if (!GetConformance().IsPdfA()) { - base.FlushObject(pdfObject, canBeInObjStm); - return; - } - MarkObjectAsMustBeFlushed(pdfObject); - if (isClosing || checker.ObjectIsChecked(pdfObject)) { - base.FlushObject(pdfObject, canBeInObjStm); - } - else { - if (!alreadyLoggedThatObjectFlushingWasNotPerformed) { - alreadyLoggedThatObjectFlushingWasNotPerformed = true; - // This log message will be printed once for one instance of the document. - ITextLogManager.GetLogger(typeof(iText.Pdfa.PdfADocument)).LogWarning(PdfALogMessageConstant.PDFA_OBJECT_FLUSHING_WAS_NOT_PERFORMED - ); - } - } - } - - /// - /// Sets the checker that defines the requirements of the PDF/A standard - /// depending on conformance. - /// - /// - /// - /// - /// - protected internal virtual void SetChecker(PdfAConformance aConformance) { - if (!GetConformance().IsPdfA()) { - return; - } - SetChecker(GetCorrectCheckerFromConformance(aConformance)); - } - - protected internal virtual void SetChecker(PdfAChecker checker) { - if (!GetConformance().IsPdfA()) { - return; - } - this.checker = checker; + PdfAChecker checker = GetCorrectCheckerFromConformance(GetConformance().GetAConformance()); ValidationContainer validationContainer = new ValidationContainer(); validationContainer.AddChecker(checker); - this.GetDiContainer().Register(typeof(ValidationContainer), validationContainer); + GetDiContainer().Register(typeof(ValidationContainer), validationContainer); + this.pdfPageFactory = new PdfAPageFactory(checker); + this.documentInfoHelper = new PdfADocumentInfoHelper(this); + this.defaultFontStrategy = new PdfADefaultFontStrategy(this); } - private void SetCheckerIfChanged() { - if (!GetConformance().IsPdfA()) { - return; - } - if (!GetDiContainer().IsRegistered(typeof(ValidationContainer))) { - return; - } - ValidationContainer validationContainer = GetDiContainer().GetInstance(); - if (validationContainer != null && !validationContainer.ContainsChecker(checker)) { - SetChecker(checker); - } - } - - private static PdfAChecker GetCorrectCheckerFromConformance(PdfAConformance aConformance) { + /// + /// Gets correct + /// + /// for specified PDF/A conformance. + /// + /// the conformance for which checker is needed + /// the correct PDF/A checker + public static PdfAChecker GetCorrectCheckerFromConformance(PdfAConformance aConformance) { PdfAChecker checker; switch (aConformance.GetPart()) { case "1": { @@ -313,78 +172,36 @@ private static PdfAChecker GetCorrectCheckerFromConformance(PdfAConformance aCon return checker; } - /// Initializes tagStructureContext to track necessary information of document's tag structure. - protected override void InitTagStructureContext() { - if (GetConformance().IsPdfA()) { - tagStructureContext = new TagStructureContext(this, GetPdfVersionForPdfA(checker.GetAConformance())); - } - else { - base.InitTagStructureContext(); - } - } - - protected override IPdfPageFactory GetPageFactory() { - if (GetConformance().IsPdfA()) { - return pdfAPageFactory; - } - else { - return base.GetPageFactory(); - } - } - - /// - /// - /// - /// - /// - protected override void FlushInfoDictionary(bool appendMode) { - if (!GetConformance().IsPdfA() || (!"4".Equals(GetConformance().GetAConformance().GetPart()))) { - base.FlushInfoDictionary(appendMode); - } - else { - if (GetCatalog().GetPdfObject().Get(PdfName.PieceInfo) != null) { - // Leave only ModDate as required by 6.1.3 File trailer of pdf/a-4 spec - GetDocumentInfo().RemoveCreationDate(); - base.FlushInfoDictionary(appendMode); - } - } - } - -//\cond DO_NOT_DOCUMENT - internal virtual bool IsClosing() { - return isClosing; - } -//\endcond - - private static PdfVersion GetPdfVersionForPdfA(PdfAConformance aConformance) { - PdfVersion version; + private static PdfVersion GetPdfVersionAccordingToConformance(PdfAConformance aConformance) { switch (aConformance.GetPart()) { case "1": { - version = PdfVersion.PDF_1_4; - break; - } - - case "2": { - version = PdfVersion.PDF_1_7; - break; + return PdfVersion.PDF_1_4; } + case "2": case "3": { - version = PdfVersion.PDF_1_7; - break; + return PdfVersion.PDF_1_7; } case "4": { - version = PdfVersion.PDF_2_0; - break; + return PdfVersion.PDF_2_0; } default: { - version = PdfVersion.PDF_1_4; - break; + return PdfVersion.PDF_1_7; } } - return version; + } + + private static PdfWriter ConfigureWriterProperties(PdfWriter writer, PdfAConformance aConformance) { + writer.GetProperties().AddPdfAXmpMetadata(aConformance); + PdfVersion aConformancePdfVersion = GetPdfVersionAccordingToConformance(aConformance); + if (writer.GetPdfVersion() != null && !writer.GetPdfVersion().Equals(aConformancePdfVersion)) { + ITextLogManager.GetLogger(typeof(iText.Pdfa.PdfADocument)).LogWarning(MessageFormatUtil.Format(PdfALogMessageConstant + .WRITER_PROPERTIES_PDF_VERSION_WAS_OVERRIDDEN, aConformancePdfVersion)); + } + writer.GetProperties().SetPdfVersion(aConformancePdfVersion); + return writer; } } } diff --git a/itext/itext.pdfa/itext/pdfa/PdfADocumentInfoHelper.cs b/itext/itext.pdfa/itext/pdfa/PdfADocumentInfoHelper.cs new file mode 100644 index 0000000000..f334370d08 --- /dev/null +++ b/itext/itext.pdfa/itext/pdfa/PdfADocumentInfoHelper.cs @@ -0,0 +1,64 @@ +/* +This file is part of the iText (R) project. +Copyright (c) 1998-2024 Apryse Group NV +Authors: Apryse Software. + +This program is offered under a commercial and under the AGPL license. +For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. + +AGPL licensing: +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +using iText.Kernel.Pdf; + +namespace iText.Pdfa { + /// The class is helper which used for PDF/A document to properly configure PDF document's info dictionary. + /// + public class PdfADocumentInfoHelper : DocumentInfoHelper { + private readonly PdfDocument pdfDocument; + + /// + /// Instantiates a new + /// + /// instance based on the document. + /// + /// the pdf document which will use that helper + public PdfADocumentInfoHelper(PdfDocument pdfDocument) { + this.pdfDocument = pdfDocument; + } + + /// + /// . + /// + public override bool ShouldAddDocumentInfoToTrailer() { + if ("4".Equals(pdfDocument.GetConformance().GetAConformance().GetPart())) { + // In case of PieceInfo == null don't add Info to trailer + return pdfDocument.GetCatalog().GetPdfObject().Get(PdfName.PieceInfo) != null; + } + return true; + } + + /// + /// . + /// + public override void AdjustDocumentInfo(PdfDocumentInfo documentInfo) { + if ("4".Equals(pdfDocument.GetConformance().GetAConformance().GetPart())) { + if (pdfDocument.GetCatalog().GetPdfObject().Get(PdfName.PieceInfo) != null) { + // Leave only ModDate as required by 6.1.3 File trailer of pdf/a-4 spec + documentInfo.RemoveCreationDate(); + } + } + } + } +} diff --git a/itext/itext.pdfa/itext/pdfa/PdfAPage.cs b/itext/itext.pdfa/itext/pdfa/PdfAPage.cs index 9fee1b9503..6368138a30 100644 --- a/itext/itext.pdfa/itext/pdfa/PdfAPage.cs +++ b/itext/itext.pdfa/itext/pdfa/PdfAPage.cs @@ -22,19 +22,24 @@ You should have received a copy of the GNU Affero General Public License */ using iText.Kernel.Geom; using iText.Kernel.Pdf; +using iText.Pdfa.Checker; namespace iText.Pdfa { //\cond DO_NOT_DOCUMENT internal class PdfAPage : PdfPage { + private readonly PdfAChecker checker; + //\cond DO_NOT_DOCUMENT - internal PdfAPage(PdfDocument pdfDocument, PageSize pageSize) + internal PdfAPage(PdfDocument pdfDocument, PageSize pageSize, PdfAChecker checker) : base(pdfDocument, pageSize) { + this.checker = checker; } //\endcond //\cond DO_NOT_DOCUMENT - internal PdfAPage(PdfDictionary pdfObject) + internal PdfAPage(PdfDictionary pdfObject, PdfAChecker checker) : base(pdfObject) { + this.checker = checker; } //\endcond @@ -42,13 +47,10 @@ public override void Flush(bool flushResourcesContentStreams) { // We check in advance whether this PdfAPage can be flushed and call the flush method only if it is. // This avoids processing actions that are invoked during flushing (for example, sending the END_PAGE event) // if the page is not actually flushed. - if (flushResourcesContentStreams || ((PdfADocument)GetDocument()).IsClosing() || ((PdfADocument)GetDocument - ()).checker.ObjectIsChecked(this.GetPdfObject())) { + if (flushResourcesContentStreams || GetDocument().IsClosing() || checker.IsPdfObjectReadyToFlush(this.GetPdfObject + ())) { base.Flush(flushResourcesContentStreams); } - else { - ((PdfADocument)GetDocument()).LogThatPdfAPageFlushingWasNotPerformed(); - } } } //\endcond diff --git a/itext/itext.pdfa/itext/pdfa/PdfAPageFactory.cs b/itext/itext.pdfa/itext/pdfa/PdfAPageFactory.cs index 4795f1a188..a871e38f15 100644 --- a/itext/itext.pdfa/itext/pdfa/PdfAPageFactory.cs +++ b/itext/itext.pdfa/itext/pdfa/PdfAPageFactory.cs @@ -22,17 +22,36 @@ You should have received a copy of the GNU Affero General Public License */ using iText.Kernel.Geom; using iText.Kernel.Pdf; +using iText.Pdfa.Checker; namespace iText.Pdfa { -//\cond DO_NOT_DOCUMENT - internal class PdfAPageFactory : IPdfPageFactory { + /// The class implements PDF page factory which is used for creating correct PDF/A documents. + public class PdfAPageFactory : IPdfPageFactory { + private readonly PdfAChecker checker; + + /// + /// Instantiates a new + /// + /// instance based on + /// . + /// + /// the PDF/A checker + public PdfAPageFactory(PdfAChecker checker) { + this.checker = checker; + } + + /// + /// . + /// public virtual PdfPage CreatePdfPage(PdfDictionary pdfObject) { - return new PdfAPage(pdfObject); + return new PdfAPage(pdfObject, checker); } + /// + /// . + /// public virtual PdfPage CreatePdfPage(PdfDocument pdfDocument, PageSize pageSize) { - return new PdfAPage(pdfDocument, pageSize); + return new PdfAPage(pdfDocument, pageSize, checker); } } -//\endcond } diff --git a/itext/itext.pdfa/itext/pdfa/PdfAXMPUtil.cs b/itext/itext.pdfa/itext/pdfa/PdfAXMPUtil.cs index 6045e693d8..ea8e8dd777 100644 --- a/itext/itext.pdfa/itext/pdfa/PdfAXMPUtil.cs +++ b/itext/itext.pdfa/itext/pdfa/PdfAXMPUtil.cs @@ -26,24 +26,6 @@ You should have received a copy of the GNU Affero General Public License namespace iText.Pdfa { /// Utilities to construct an XMP for a PDF/A file. public class PdfAXMPUtil { - public const String PDF_UA_EXTENSION = " \n" + " \n" - + " \n" - + " \n" + " \n" + " \n" - + " \n" - + " pdfuaid\n" + " PDF/UA identification schema\n" - + " \n" + " \n" + " \n" - + " internal\n" + " PDF/UA version identifier\n" - + " part\n" + " Integer\n" - + " \n" + " \n" + " internal\n" - + " PDF/UA amendment identifier\n" - + " amd\n" + " Text\n" - + " \n" + " \n" + " internal\n" - + " PDF/UA corrigenda identifier\n" - + " corr\n" + " Text\n" - + " \n" + " \n" + " \n" - + " \n" + " \n" + " \n" + - " \n" + " \n" + " "; - public static bool IsUtf8(byte[] array) { UTF8Encoding encoding = new UTF8Encoding(false, true); try { diff --git a/itext/itext.pdfa/itext/pdfa/checker/PdfAChecker.cs b/itext/itext.pdfa/itext/pdfa/checker/PdfAChecker.cs index c2af6e997a..4de59021e4 100644 --- a/itext/itext.pdfa/itext/pdfa/checker/PdfAChecker.cs +++ b/itext/itext.pdfa/itext/pdfa/checker/PdfAChecker.cs @@ -22,6 +22,8 @@ You should have received a copy of the GNU Affero General Public License */ using System; using System.Collections.Generic; +using Microsoft.Extensions.Logging; +using iText.Commons; using iText.IO.Colors; using iText.Kernel.Colors; using iText.Kernel.Font; @@ -30,6 +32,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Kernel.Pdf.Colorspace; using iText.Kernel.Validation; using iText.Kernel.Validation.Context; +using iText.Pdfa.Logs; namespace iText.Pdfa.Checker { /// @@ -122,6 +125,10 @@ public abstract class PdfAChecker : IValidationChecker { private bool fullCheckMode = false; + private bool alreadyLoggedThatPageFlushingWasNotPerformed = false; + + private bool alreadyLoggedThatObjectFlushingWasNotPerformed = false; + /// Creates a PdfAChecker with the required conformance. /// the required conformance protected internal PdfAChecker(PdfAConformance aConformance) { @@ -156,6 +163,9 @@ public virtual void CheckDocument(PdfCatalog catalog) { CheckOpenAction(catalogDict.Get(PdfName.OpenAction)); } + /// + /// . + /// public virtual void Validate(IValidationContext context) { CanvasGraphicsState gState = null; if (context is IGraphicStateValidationParameter) { @@ -261,12 +271,39 @@ public virtual void Validate(IValidationContext context) { } } + /// + /// . + /// + public virtual bool IsPdfObjectReadyToFlush(PdfObject @object) { + if (checkedObjects.Contains(@object)) { + return true; + } + if (@object is PdfDictionary && PdfName.Page.Equals(((PdfDictionary)@object).GetAsName(PdfName.Type))) { + if (!alreadyLoggedThatPageFlushingWasNotPerformed) { + alreadyLoggedThatPageFlushingWasNotPerformed = true; + // This log message will be printed once for one instance of the document. + ITextLogManager.GetLogger(typeof(iText.Pdfa.Checker.PdfAChecker)).LogWarning(PdfALogMessageConstant.PDFA_PAGE_FLUSHING_WAS_NOT_PERFORMED + ); + } + } + else { + if (!alreadyLoggedThatObjectFlushingWasNotPerformed) { + alreadyLoggedThatObjectFlushingWasNotPerformed = true; + // This log message will be printed once for one instance of the document. + ITextLogManager.GetLogger(typeof(iText.Pdfa.Checker.PdfAChecker)).LogWarning(PdfALogMessageConstant.PDFA_OBJECT_FLUSHING_WAS_NOT_PERFORMED + ); + } + } + return false; + } + /// /// This method checks all requirements that must be fulfilled by a page in a /// PDF/A document. /// /// the page that must be checked public virtual void CheckSinglePage(PdfPage page) { + SetPdfAOutputIntentColorSpace(page.GetDocument().GetCatalog().GetPdfObject()); CheckPage(page); } @@ -353,16 +390,6 @@ public virtual void SetFullCheckMode(bool fullCheckMode) { this.fullCheckMode = fullCheckMode; } - /// - /// Remembers which objects have already been checked, in order to avoid - /// redundant checks. - /// - /// the object to check - /// whether or not the object has already been checked - public virtual bool ObjectIsChecked(PdfObject @object) { - return checkedObjects.Contains(@object); - } - /// /// This method checks compliance of the tag structure elements, such as struct elements /// or parent tree entries. diff --git a/itext/itext.pdfa/itext/pdfa/logs/PdfALogMessageConstant.cs b/itext/itext.pdfa/itext/pdfa/logs/PdfALogMessageConstant.cs index 7baf45638f..205aa0d66b 100644 --- a/itext/itext.pdfa/itext/pdfa/logs/PdfALogMessageConstant.cs +++ b/itext/itext.pdfa/itext/pdfa/logs/PdfALogMessageConstant.cs @@ -31,6 +31,8 @@ public class PdfALogMessageConstant { public const String PDFA_OBJECT_FLUSHING_WAS_NOT_PERFORMED = "Object flushing was not performed. Object in PDF/A mode can only be flushed if the document is closed or " + "if this object has already been checked for compliance with PDF/A rules."; + public const String WRITER_PROPERTIES_PDF_VERSION_WAS_OVERRIDDEN = "Pdf version from writer properties isn't compatible with specified PDF/A conformance, it was overridden to {0} version."; + private PdfALogMessageConstant() { } //Private constructor will prevent the instantiation of this class directly diff --git a/itext/itext.pdfua/itext/pdfua/PdfUADocument.cs b/itext/itext.pdfua/itext/pdfua/PdfUADocument.cs index fa406d8991..3ea149f7de 100644 --- a/itext/itext.pdfua/itext/pdfua/PdfUADocument.cs +++ b/itext/itext.pdfua/itext/pdfua/PdfUADocument.cs @@ -22,6 +22,7 @@ You should have received a copy of the GNU Affero General Public License */ using Microsoft.Extensions.Logging; using iText.Commons; +using iText.Commons.Utils; using iText.Kernel.Pdf; using iText.Kernel.Validation; using iText.Pdfua.Checkers; @@ -35,14 +36,8 @@ namespace iText.Pdfua { /// It will add necessary validation to guide the user to create a PDF/UA compliant document. /// public class PdfUADocument : PdfDocument { - private static readonly IPdfPageFactory pdfPageFactory = new PdfUAPageFactory(); - private static readonly ILogger LOGGER = ITextLogManager.GetLogger(typeof(iText.Pdfua.PdfUADocument)); - private bool warnedOnPageFlush = false; - - private PdfConformance conformance; - /// Creates a PdfUADocument instance. /// The writer to write the PDF document. /// The configuration for the PDF/UA document. @@ -56,8 +51,13 @@ public PdfUADocument(PdfWriter writer, PdfUAConfig config) /// The configuration for the PDF/UA document. public PdfUADocument(PdfWriter writer, DocumentProperties properties, PdfUAConfig config) : base(ConfigureWriterProperties(writer), properties) { - conformance = new PdfConformance(config.GetConformance()); + this.pdfConformance = new PdfConformance(config.GetConformance()); SetupUAConfiguration(config); + ValidationContainer validationContainer = new ValidationContainer(); + PdfUA1Checker checker = new PdfUA1Checker(this); + validationContainer.AddChecker(checker); + this.GetDiContainer().Register(typeof(ValidationContainer), validationContainer); + this.pdfPageFactory = new PdfUAPageFactory(checker); } /// Creates a PdfUADocument instance. @@ -75,48 +75,26 @@ public PdfUADocument(PdfReader reader, PdfWriter writer, PdfUAConfig config) /// The configuration for the PDF/UA document. public PdfUADocument(PdfReader reader, PdfWriter writer, StampingProperties properties, PdfUAConfig config ) - : base(reader, ConfigureWriterProperties(writer), properties) { - conformance = base.GetConformance(); - SetupUAConfiguration(config); + : base(reader, writer, properties) { if (!GetConformance().IsPdfUA()) { LOGGER.LogWarning(PdfUALogMessageConstants.PDF_TO_PDF_UA_CONVERSION_IS_NOT_SUPPORTED); } + SetupUAConfiguration(config); + ValidationContainer validationContainer = new ValidationContainer(); + PdfUA1Checker checker = new PdfUA1Checker(this); + validationContainer.AddChecker(checker); + this.GetDiContainer().Register(typeof(ValidationContainer), validationContainer); + this.pdfPageFactory = new PdfUAPageFactory(checker); } - /// The PageFactory for the PDF/UA document. - protected override IPdfPageFactory GetPageFactory() { - return pdfPageFactory; - } - - public override PdfConformance GetConformance() { - return conformance; - } - -//\cond DO_NOT_DOCUMENT - /// Returns if the document is in the closing state. - /// true if the document is closing, false otherwise. - internal virtual bool IsClosing() { - return this.isClosing; - } -//\endcond - -//\cond DO_NOT_DOCUMENT - /// Warns the user that the page is being flushed. - /// - /// Warns the user that the page is being flushed. - /// Will only warn once. - /// - internal virtual void WarnOnPageFlush() { - if (!warnedOnPageFlush) { - LOGGER.LogWarning(PdfUALogMessageConstants.PAGE_FLUSHING_DISABLED); - warnedOnPageFlush = true; + private static PdfWriter ConfigureWriterProperties(PdfWriter writer) { + writer.GetProperties().AddPdfUaXmpMetadata(PdfUAConformance.PDF_UA_1); + if (writer.GetPdfVersion() != null && !writer.GetPdfVersion().Equals(PdfVersion.PDF_1_7)) { + ITextLogManager.GetLogger(typeof(iText.Pdfua.PdfUADocument)).LogWarning(MessageFormatUtil.Format(PdfUALogMessageConstants + .WRITER_PROPERTIES_PDF_VERSION_WAS_OVERRIDDEN, PdfVersion.PDF_1_7)); + writer.GetProperties().SetPdfVersion(PdfVersion.PDF_1_7); } - } -//\endcond - - /// Disables the warning for page flushing. - public virtual void DisablePageFlushingWarning() { - warnedOnPageFlush = true; + return writer; } private void SetupUAConfiguration(PdfUAConfig config) { @@ -126,15 +104,6 @@ private void SetupUAConfiguration(PdfUAConfig config) { this.GetCatalog().SetLang(new PdfString(config.GetLanguage())); PdfDocumentInfo info = this.GetDocumentInfo(); info.SetTitle(config.GetTitle()); - //validation - ValidationContainer validationContainer = new ValidationContainer(); - validationContainer.AddChecker(new PdfUA1Checker(this)); - this.GetDiContainer().Register(typeof(ValidationContainer), validationContainer); - } - - private static PdfWriter ConfigureWriterProperties(PdfWriter writer) { - writer.GetProperties().AddUAXmpMetadata(); - return writer; } } } diff --git a/itext/itext.pdfua/itext/pdfua/PdfUAPage.cs b/itext/itext.pdfua/itext/pdfua/PdfUAPage.cs index 604f5aad52..94b221a6a7 100644 --- a/itext/itext.pdfua/itext/pdfua/PdfUAPage.cs +++ b/itext/itext.pdfua/itext/pdfua/PdfUAPage.cs @@ -22,25 +22,29 @@ You should have received a copy of the GNU Affero General Public License */ using iText.Kernel.Geom; using iText.Kernel.Pdf; +using iText.Pdfua.Checkers; namespace iText.Pdfua { //\cond DO_NOT_DOCUMENT internal class PdfUAPage : PdfPage { - protected internal PdfUAPage(PdfDictionary pdfObject) + private readonly PdfUA1Checker checker; + + protected internal PdfUAPage(PdfDictionary pdfObject, PdfUA1Checker checker) : base(pdfObject) { + this.checker = checker; } - protected internal PdfUAPage(PdfDocument pdfDocument, PageSize pageSize) + protected internal PdfUAPage(PdfDocument pdfDocument, PageSize pageSize, PdfUA1Checker checker) : base(pdfDocument, pageSize) { + this.checker = checker; } public override void Flush(bool flushResourcesContentStreams) { - PdfDocument document = GetDocument(); - if (((PdfUADocument)document).IsClosing()) { + if (GetDocument().IsClosing()) { base.Flush(flushResourcesContentStreams); return; } - ((PdfUADocument)document).WarnOnPageFlush(); + checker.WarnOnPageFlush(); } } //\endcond diff --git a/itext/itext.pdfua/itext/pdfua/PdfUAPageFactory.cs b/itext/itext.pdfua/itext/pdfua/PdfUAPageFactory.cs index b074c5a8b2..fc7a8b0643 100644 --- a/itext/itext.pdfua/itext/pdfua/PdfUAPageFactory.cs +++ b/itext/itext.pdfua/itext/pdfua/PdfUAPageFactory.cs @@ -22,14 +22,25 @@ You should have received a copy of the GNU Affero General Public License */ using iText.Kernel.Geom; using iText.Kernel.Pdf; +using iText.Pdfua.Checkers; namespace iText.Pdfua { //\cond DO_NOT_DOCUMENT + /// The class implements PDF page factory which is used for creating correct PDF/UA documents. internal class PdfUAPageFactory : IPdfPageFactory { - public PdfUAPageFactory() { + private readonly PdfUA1Checker checker; + + /// + /// Instantiates a new + /// + /// instance based on + /// . + /// + /// the PDF/UA checker + public PdfUAPageFactory(PdfUA1Checker checker) { + this.checker = checker; } - //empty constructor /// /// the /// @@ -39,7 +50,7 @@ public PdfUAPageFactory() { /// /// The pdf page. public virtual PdfPage CreatePdfPage(PdfDictionary pdfObject) { - return new PdfUAPage(pdfObject); + return new PdfUAPage(pdfObject, checker); } /// @@ -54,7 +65,7 @@ public virtual PdfPage CreatePdfPage(PdfDictionary pdfObject) { /// /// The Pdf page. public virtual PdfPage CreatePdfPage(PdfDocument pdfDocument, PageSize pageSize) { - return new PdfUAPage(pdfDocument, pageSize); + return new PdfUAPage(pdfDocument, pageSize, checker); } } //\endcond diff --git a/itext/itext.pdfua/itext/pdfua/checkers/PdfUA1Checker.cs b/itext/itext.pdfua/itext/pdfua/checkers/PdfUA1Checker.cs index fc1d33ec95..58fcd1cbbe 100644 --- a/itext/itext.pdfua/itext/pdfua/checkers/PdfUA1Checker.cs +++ b/itext/itext.pdfua/itext/pdfua/checkers/PdfUA1Checker.cs @@ -22,6 +22,8 @@ You should have received a copy of the GNU Affero General Public License */ using System; using System.Collections.Generic; +using Microsoft.Extensions.Logging; +using iText.Commons; using iText.Commons.Datastructures; using iText.Commons.Utils; using iText.Kernel.Font; @@ -37,6 +39,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Pdfua.Checkers.Utils.Headings; using iText.Pdfua.Checkers.Utils.Tables; using iText.Pdfua.Exceptions; +using iText.Pdfua.Logs; namespace iText.Pdfua.Checkers { /// The class defines the requirements of the PDF/UA-1 standard. @@ -54,6 +57,8 @@ public class PdfUA1Checker : IValidationChecker { private readonly PdfUAValidationContext context; + private bool warnedOnPageFlush = false; + /// Creates PdfUA1Checker instance with PDF document which will be validated against PDF/UA-1 standard. /// /// the document to validate @@ -64,6 +69,9 @@ public PdfUA1Checker(PdfDocument pdfDocument) { this.headingsChecker = new HeadingsChecker(context); } + /// + /// . + /// public virtual void Validate(IValidationContext context) { switch (context.GetType()) { case ValidationType.PDF_DOCUMENT: { @@ -120,6 +128,22 @@ public virtual void Validate(IValidationContext context) { } } + /// + /// . + /// + public virtual bool IsPdfObjectReadyToFlush(PdfObject @object) { + return true; + } + + /// Logs a warn on page flushing that page flushing is disabled in PDF/UA mode. + public virtual void WarnOnPageFlush() { + if (!warnedOnPageFlush) { + ITextLogManager.GetLogger(typeof(iText.Pdfua.Checkers.PdfUA1Checker)).LogWarning(PdfUALogMessageConstants. + PAGE_FLUSHING_DISABLED); + warnedOnPageFlush = true; + } + } + /// Verify the conformity of the file specification dictionary. /// /// the diff --git a/itext/itext.pdfua/itext/pdfua/logs/PdfUALogMessageConstants.cs b/itext/itext.pdfua/itext/pdfua/logs/PdfUALogMessageConstants.cs index 017d5335de..18689ade4c 100644 --- a/itext/itext.pdfua/itext/pdfua/logs/PdfUALogMessageConstants.cs +++ b/itext/itext.pdfua/itext/pdfua/logs/PdfUALogMessageConstants.cs @@ -30,6 +30,8 @@ public sealed class PdfUALogMessageConstants { public const String PDF_TO_PDF_UA_CONVERSION_IS_NOT_SUPPORTED = "PDF to PDF/UA conversion is not supported."; + public const String WRITER_PROPERTIES_PDF_VERSION_WAS_OVERRIDDEN = "Pdf version from writer properties isn't compatible with specified PDF/UA conformance, it was overridden to {0} version."; + private PdfUALogMessageConstants() { } // empty constructor diff --git a/itext/itext.sign/itext.sign.csproj b/itext/itext.sign/itext.sign.csproj index ff6678b37a..b1f45cc7a4 100644 --- a/itext/itext.sign/itext.sign.csproj +++ b/itext/itext.sign/itext.sign.csproj @@ -25,6 +25,7 @@ + diff --git a/itext/itext.sign/itext/signatures/PdfSigner.cs b/itext/itext.sign/itext/signatures/PdfSigner.cs index 964c31cc2b..b593ff6125 100644 --- a/itext/itext.sign/itext/signatures/PdfSigner.cs +++ b/itext/itext.sign/itext/signatures/PdfSigner.cs @@ -46,10 +46,12 @@ You should have received a copy of the GNU Affero General Public License using iText.Kernel.Pdf; using iText.Kernel.Pdf.Annot; using iText.Kernel.Pdf.Tagutils; +using iText.Kernel.Validation; using iText.Kernel.Validation.Context; using iText.Layout.Properties; using iText.Layout.Tagging; using iText.Pdfa; +using iText.Pdfa.Checker; using iText.Signatures.Cms; using iText.Signatures.Exceptions; using iText.Signatures.Mac; @@ -237,7 +239,9 @@ internal PdfSigner(PdfDocument document, Stream outputStream, MemoryStream tempo /// protected internal virtual PdfDocument InitDocument(PdfReader reader, PdfWriter writer, StampingProperties properties) { - return new PdfAAgnosticPdfDocument(reader, writer, properties); + // TODO DEVSIX-8676 Enable keeping A and UA conformance in PdfSigner + // TODO DEVSIX-8677 let users preserve document's conformance without knowing upfront their conformance + return new PdfSigner.PdfSignerDocument(reader, writer, properties); } /// Sets the properties to be used in signing operations. @@ -1466,5 +1470,21 @@ public virtual Stream GetDataToSign() { //\endcond internal delegate byte[] ISignatureDataProvider(PdfSigner.SignatureApplier applier); + + private class PdfSignerDocument : PdfDocument { + public PdfSignerDocument(PdfReader reader, PdfWriter writer, StampingProperties properties) + : base(reader, writer, properties) { + if (GetConformance().IsPdfA()) { + PdfAChecker checker = PdfADocument.GetCorrectCheckerFromConformance(GetConformance().GetAConformance()); + ValidationContainer validationContainer = new ValidationContainer(); + validationContainer.AddChecker(checker); + GetDiContainer().Register(typeof(ValidationContainer), validationContainer); + this.pdfPageFactory = new PdfAPageFactory(checker); + this.documentInfoHelper = new PdfADocumentInfoHelper(this); + this.defaultFontStrategy = new PdfADefaultFontStrategy(this); + SetFlushUnusedObjects(true); + } + } + } } } diff --git a/itext/itext.sign/itext/signatures/validation/DocumentRevisionsValidator.cs b/itext/itext.sign/itext/signatures/validation/DocumentRevisionsValidator.cs index 6b38310377..66e1bcaa3d 100644 --- a/itext/itext.sign/itext/signatures/validation/DocumentRevisionsValidator.cs +++ b/itext/itext.sign/itext/signatures/validation/DocumentRevisionsValidator.cs @@ -747,8 +747,8 @@ private bool CreateDocumentAndPerformOperation(DocumentRevision revision, PdfDoc report, Func operation) { try { using (Stream inputStream = CreateInputStreamFromRevision(originalDocument, revision)) { - using (PdfReader reader = new PdfReader(inputStream).SetStrictnessLevel(PdfReader.StrictnessLevel.CONSERVATIVE - )) { + using (PdfReader reader = new PdfReader(inputStream, originalDocument.GetReader().GetPropertiesCopy()).SetStrictnessLevel + (PdfReader.StrictnessLevel.CONSERVATIVE)) { using (PdfDocument documentWithRevision = new PdfDocument(reader, new DocumentProperties().SetEventCountingMetaInfo (metaInfo))) { return (bool)operation.Invoke(documentWithRevision); diff --git a/itext/itext.sign/itext/signatures/validation/SignatureValidator.cs b/itext/itext.sign/itext/signatures/validation/SignatureValidator.cs index 15b2338907..199f9f763b 100644 --- a/itext/itext.sign/itext/signatures/validation/SignatureValidator.cs +++ b/itext/itext.sign/itext/signatures/validation/SignatureValidator.cs @@ -294,9 +294,9 @@ private ValidationReport Validate(String signatureName) { foreach (String fieldName in signatureNames) { ValidationReport subReport = new ValidationReport(); try { - using (PdfDocument doc = new PdfDocument(new PdfReader(util.ExtractRevision(fieldName)).SetStrictnessLevel - (PdfReader.StrictnessLevel.CONSERVATIVE), new DocumentProperties().SetEventCountingMetaInfo(metaInfo)) - ) { + using (PdfDocument doc = new PdfDocument(new PdfReader(util.ExtractRevision(fieldName), originalDocument.GetReader + ().GetPropertiesCopy()).SetStrictnessLevel(PdfReader.StrictnessLevel.CONSERVATIVE), new DocumentProperties + ().SetEventCountingMetaInfo(metaInfo))) { subReport.Merge(ValidateLatestSignature(doc)); } } diff --git a/port-hash b/port-hash index d35473a50b..9413a40b2c 100644 --- a/port-hash +++ b/port-hash @@ -1 +1 @@ -9fe2316b0ddd5adea465af2301807686b70d4326 +e84bb3e25bfeda609158e655bd754ec159ce6db3