Skip to content

Commit

Permalink
Merge branch 'develop' into devsecops
Browse files Browse the repository at this point in the history
  • Loading branch information
aleks-ivanov committed Aug 18, 2024
2 parents 0934e00 + 1febf6a commit 0f0548b
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
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 <https://www.gnu.org/licenses/>.
*/
using iText.Commons.Actions.Data;
using iText.IO.Source;
using iText.Kernel.Logs;
using iText.Kernel.Pdf;
using iText.Test;
using iText.Test.Attributes;

namespace iText.Kernel.Actions.Events {
[NUnit.Framework.Category("UnitTest")]
public class AddFingerPrintEventTest : ExtendedITextTest {
[NUnit.Framework.Test]
public virtual void NullDocumentTest() {
AddFingerPrintEvent addFingerPrintEvent = new AddFingerPrintEvent(null);
NUnit.Framework.Assert.DoesNotThrow(() => addFingerPrintEvent.DoAction());
}

[NUnit.Framework.Test]
[LogMessage(KernelLogMessageConstant.FINGERPRINT_DISABLED_BUT_NO_REQUIRED_LICENCE)]
public virtual void DisableFingerPrintAGPLTest() {
using (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
using (PdfDocument doc = new PdfDocument(new PdfWriter(outputStream))) {
doc.GetFingerPrint().DisableFingerPrint();
NUnit.Framework.Assert.DoesNotThrow(() => doc.Close());
}
}
}

[NUnit.Framework.Test]
public virtual void EnabledFingerPrintAGPLTest() {
using (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
using (PdfDocument doc = new PdfDocument(new PdfWriter(outputStream))) {
NUnit.Framework.Assert.DoesNotThrow(() => doc.Close());
}
}
}

[NUnit.Framework.Test]
public virtual void DisableFingerPrintNoProcessorForProductTest() {
using (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
using (PdfDocument doc = new PdfDocument(new PdfWriter(outputStream))) {
ProductData productData = new ProductData("public product name", "product name", "1", 2000, 2024);
doc.GetFingerPrint().RegisterProduct(productData);
NUnit.Framework.Assert.DoesNotThrow(() => doc.Close());
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,12 @@ public virtual void DuplicateTest() {
fingerPrint.RegisterProduct(productData);
NUnit.Framework.Assert.IsFalse(fingerPrint.RegisterProduct(duplicateProductData));
}

[NUnit.Framework.Test]
public virtual void DisableFingerPrintTest() {
FingerPrint fingerPrint = new FingerPrint();
fingerPrint.DisableFingerPrint();
NUnit.Framework.Assert.IsFalse(fingerPrint.IsFingerPrintEnabled());
}
}
}
37 changes: 37 additions & 0 deletions itext.tests/itext.kernel.tests/itext/kernel/pdf/TrailerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ You should have received a copy of the GNU Affero General Public License
using iText.Commons.Utils;
using iText.Kernel.Actions.Data;
using iText.Kernel.Font;
using iText.Kernel.Logs;
using iText.Kernel.Pdf.Canvas;
using iText.Test;
using iText.Test.Attributes;

namespace iText.Kernel.Pdf {
[NUnit.Framework.Category("IntegrationTest")]
Expand Down Expand Up @@ -137,6 +139,35 @@ public virtual void ExistingTrailerValuesWithStandardizedNameTest() {
}
}

[NUnit.Framework.Test]
public virtual void EnableFingerprintInAGPLModeTest() {
PdfDocument pdf = new PdfDocument(new PdfWriter(destinationFolder + "enableFingerprintInAGPLMode.pdf"));
pdf.RegisterProduct(this.productData);
PdfPage page = pdf.AddNewPage();
PdfCanvas canvas = new PdfCanvas(page);
canvas.BeginText().SetFontAndSize(PdfFontFactory.CreateFont(), 12f).ShowText("Hello World").EndText();
pdf.Close();
NUnit.Framework.Assert.IsTrue(DoesTrailerContainFingerprint(new FileInfo(destinationFolder + "enableFingerprintInAGPLMode.pdf"
), MessageFormatUtil.Format("%iText-{0}-{1}\n", productData.GetProductName(), productData.GetVersion()
)));
}

[NUnit.Framework.Test]
[LogMessage(KernelLogMessageConstant.FINGERPRINT_DISABLED_BUT_NO_REQUIRED_LICENCE)]
public virtual void TryDisablingFingerprintInAGPLModeTest() {
PdfDocument pdf = new PdfDocument(new PdfWriter(destinationFolder + "tryDisablingFingerprintInAGPLMode.pdf"
));
pdf.RegisterProduct(this.productData);
PdfPage page = pdf.AddNewPage();
PdfCanvas canvas = new PdfCanvas(page);
canvas.BeginText().SetFontAndSize(PdfFontFactory.CreateFont(), 12f).ShowText("Hello World").EndText();
pdf.GetFingerPrint().DisableFingerPrint();
pdf.Close();
NUnit.Framework.Assert.IsTrue(DoesTrailerContainFingerprint(new FileInfo(destinationFolder + "tryDisablingFingerprintInAGPLMode.pdf"
), MessageFormatUtil.Format("%iText-{0}-{1}\n", productData.GetProductName(), productData.GetVersion()
)));
}

private bool DoesTrailerContainFingerprint(FileInfo file, String fingerPrint) {
using (FileStream raf = FileUtil.GetRandomAccessFile(file)) {
// put the pointer at the end of the file
Expand All @@ -145,13 +176,19 @@ private bool DoesTrailerContainFingerprint(FileInfo file, String fingerPrint) {
String coreProductData = "%iText-Core-" + ITextCoreProductData.GetInstance().GetVersion();
String templine = "";
while (!templine.Contains(coreProductData)) {
if (raf.Position <= 2) {
return false;
}
templine = (char)raf.ReadByte() + templine;
raf.Seek(raf.Position - 2);
}
// look for fingerprint
char read = ' ';
templine = "";
while (read != '%') {
if (raf.Position <= 2) {
return false;
}
read = (char)raf.ReadByte();
templine = read + templine;
raf.Seek(raf.Position - 2);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
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 <https://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using iText.Commons;
using iText.Commons.Actions;
using iText.Commons.Actions.Data;
using iText.Commons.Actions.Processors;
using iText.Commons.Utils;
using iText.Kernel.Actions.Data;
using iText.Kernel.Logs;
using iText.Kernel.Pdf;

namespace iText.Kernel.Actions.Events {
/// <summary>This class is responsible for adding a fingerprint.</summary>
public sealed class AddFingerPrintEvent : AbstractITextConfigurationEvent {
private readonly WeakReference document;

private static readonly ILogger LOGGER = ITextLogManager.GetLogger(typeof(iText.Kernel.Actions.Events.AddFingerPrintEvent
));

private const String AGPL_MODE = "AGPL";

/// <summary>Creates a new instance of the AddFingerPrintEvent.</summary>
/// <param name="document">document in which the fingerprint will be added</param>
public AddFingerPrintEvent(PdfDocument document)
: base() {
this.document = new WeakReference(document);
}

/// <summary>Adds fingerprint to the document.</summary>
protected internal override void DoAction() {
PdfDocument pdfDocument = (PdfDocument)document.Target;
if (pdfDocument == null) {
return;
}
FingerPrint fingerPrint = pdfDocument.GetFingerPrint();
ICollection<ProductData> products = fingerPrint.GetProducts();
//if fingerprint is disabled and all licence types isn't AGPL then no actions required
if (!fingerPrint.IsFingerPrintEnabled()) {
bool nonAGPLMode = true;
foreach (ProductData productData in products) {
ITextProductEventProcessor processor = GetActiveProcessor(productData.GetProductName());
if (processor == null) {
continue;
}
if (AGPL_MODE.Equals(processor.GetUsageType())) {
nonAGPLMode = false;
break;
}
}
if (nonAGPLMode) {
return;
}
LOGGER.LogWarning(KernelLogMessageConstant.FINGERPRINT_DISABLED_BUT_NO_REQUIRED_LICENCE);
}
PdfWriter writer = pdfDocument.GetWriter();
if (products.IsEmpty()) {
writer.WriteString(MessageFormatUtil.Format("%iText-{0}-no-registered-products\n", ITextCoreProductData.GetInstance
().GetVersion()));
return;
}
foreach (ProductData productData in products) {
writer.WriteString(MessageFormatUtil.Format("%iText-{0}-{1}\n", productData.GetPublicProductName(), productData
.GetVersion()));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public sealed class KernelLogMessageConstant {
public const String DUPLICATE_ENTRIES_IN_ORDER_ARRAY_REMOVED = "Duplicated entries in order array are " +
"removed";

public const String FINGERPRINT_DISABLED_BUT_NO_REQUIRED_LICENCE = "Fingerprint disabling is only " + "available in non AGPL mode. Fingerprint will be added at the end of the document.";

private KernelLogMessageConstant() {
}
//Private constructor will prevent the instantiation of this class directly
Expand Down
20 changes: 18 additions & 2 deletions itext/itext.kernel/itext/kernel/pdf/FingerPrint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,34 @@ namespace iText.Kernel.Pdf {
/// <summary>Data container for debugging information.</summary>
/// <remarks>
/// Data container for debugging information. This class keeps a record of every registered product that
/// was involved in the creation of a certain PDF file. This information can then be used to log to the
/// logger or to the file.
/// was involved in the creation of a certain PDF file.
/// </remarks>
public class FingerPrint {
private ICollection<ProductData> productDataSet;

private bool fingerPrintEnabled = true;

/// <summary>Default constructor.</summary>
/// <remarks>Default constructor. Initializes the productDataSet.</remarks>
public FingerPrint() {
this.productDataSet = new LinkedHashSet<ProductData>();
}

/// <summary>This method is used to disable iText fingerprint.</summary>
/// <remarks>
/// This method is used to disable iText fingerprint.
/// IText fingerPrint can only be disabled if all products are in non AGPL mode.
/// </remarks>
public virtual void DisableFingerPrint() {
fingerPrintEnabled = false;
}

/// <summary>This method is used to check iText fingerprint state.</summary>
/// <returns>true if fingerprint will be added to the document</returns>
public virtual bool IsFingerPrintEnabled() {
return fingerPrintEnabled;
}

/// <summary>Registers a product to be added to the fingerprint or other debugging info.</summary>
/// <param name="productData">ProductData to be added</param>
/// <returns>true if the fingerprint did not already contain the specified element</returns>
Expand Down
28 changes: 3 additions & 25 deletions itext/itext.kernel/itext/kernel/pdf/PdfXrefTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ You should have received a copy of the GNU Affero General Public License
using System.Text;
using Microsoft.Extensions.Logging;
using iText.Commons;
using iText.Commons.Actions.Data;
using iText.Commons.Actions;
using iText.Commons.Utils;
using iText.IO.Source;
using iText.Kernel.Actions.Data;
using iText.Kernel.Actions.Events;
using iText.Kernel.Exceptions;

namespace iText.Kernel.Pdf {
Expand Down Expand Up @@ -184,28 +184,6 @@ public virtual PdfIndirectReference Get(int index) {
return xref[index];
}

/// <summary>Convenience method to write the fingerprint preceding the trailer.</summary>
/// <remarks>
/// Convenience method to write the fingerprint preceding the trailer.
/// The fingerprint contains information on iText products used in the generation or manipulation
/// of an outputted PDF file.
/// </remarks>
/// <param name="document">pdfDocument to write the fingerprint to</param>
protected internal static void WriteKeyInfo(PdfDocument document) {
PdfWriter writer = document.GetWriter();
ICollection<ProductData> products = document.GetFingerPrint().GetProducts();
if (products.IsEmpty()) {
writer.WriteString(MessageFormatUtil.Format("%iText-{0}-no-registered-products\n", ITextCoreProductData.GetInstance
().GetVersion()));
}
else {
foreach (ProductData productData in products) {
writer.WriteString(MessageFormatUtil.Format("%iText-{0}-{1}\n", productData.GetPublicProductName(), productData
.GetVersion()));
}
}
}

/// <summary>Creates next available indirect reference.</summary>
/// <param name="document">
/// is the current
Expand Down Expand Up @@ -400,7 +378,7 @@ protected internal virtual void WriteXrefTableAndTrailer(PdfDocument document, P
writer.Write(document.GetTrailer());
writer.Write('\n');
}
WriteKeyInfo(document);
EventManager.GetInstance().OnEvent(new AddFingerPrintEvent(document));
writer.WriteString("startxref\n").WriteLong(startxref).WriteString("\n%%EOF\n");
xref = null;
freeReferencesLinkedList.Clear();
Expand Down
2 changes: 1 addition & 1 deletion port-hash
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d5b02fbcfb969e96fbe636524ab8f440426f99d7
c3c3b73f49c22e127f2047cf7b76862df3a75d75

0 comments on commit 0f0548b

Please sign in to comment.