diff --git a/.github/workflows/test-net-framework-samples.yml b/.github/workflows/test-net-framework-samples.yml index 7bd74bc..9943580 100644 --- a/.github/workflows/test-net-framework-samples.yml +++ b/.github/workflows/test-net-framework-samples.yml @@ -12,7 +12,7 @@ on: jobs: test-samples: - runs-on: windows-2019 + runs-on: windows-2022 defaults: run: shell: bash @@ -93,7 +93,8 @@ jobs: 'Other/StreamIO/', 'Printing/PrintPDF/', 'Printing/PrintPDFGUI/', - 'Security/AddDigitalSignature/', + 'Security/AddDigitalSignatureCMS/', + 'Security/AddDigitalSignatureRFC3161/', 'Security/AddRegexRedaction/', 'Security/Redactions/', 'Text/AddGlyphs/', diff --git a/ContentModification/CreateLayer/CreateLayer.cs b/ContentModification/CreateLayer/CreateLayer.cs index 289f1b4..8a7dfe4 100644 --- a/ContentModification/CreateLayer/CreateLayer.cs +++ b/ContentModification/CreateLayer/CreateLayer.cs @@ -1,18 +1,15 @@ +using Datalogics.PDFL; using System; using System.Collections.Generic; -using System.Text; -using Datalogics.PDFL; /* - * This sample adds an Optional Content Group (a layer) to a PDF document and - * then adds an image to that layer. + * This sample adds Optional Content Groups (layers) to a PDF document and + * then adds Content to those layers. * * The related ChangeLayerConfiguration program makes layers visible or invisible. * - * You can toggle back and forth to make the layer (the duck image) visible or invisible - * in the PDF file. Open the output PDF document in a PDF Viewer, click View and select - * Show/Hide. Select Navigation Panes and Layers to display the layers in the PDF file. - * Click on the box next to the name of the layer. + * You can toggle back and forth to make a layer visible or invisible + * in a PDF Viewer. * */ namespace CreateLayer @@ -38,60 +35,120 @@ static void Main(string[] args) Console.WriteLine("Input file: " + sInput + ", writing to " + sOutput); - Document doc = new Document(sInput); - - Console.WriteLine("Opened a document."); - - Page pg = doc.GetPage(0); - Image img = (pg.Content.GetElement(0) as Image); - - // Containers, Forms and Annotations can be attached to an - // OptionalContentGroup; other content (like Image) can - // be made optional by placing it inside a Container - Container container = new Container(); - container.Content = new Content(); - container.Content.AddElement(img); + using (Document doc = new Document(sInput)) + { + Console.WriteLine("Opened a document."); + + using (Page pg = doc.GetPage(0)) + { + Image image = (Image)pg.Content.GetElement(0); + image.Matrix = new Matrix(image.Matrix.A * .5, 0, 0, image.Matrix.D * .5, image.Matrix.H, image.Matrix.V); + + Image image2 = new Image(Library.ResourceDirectory + "Sample_Input/Image.png"); + + Text text = new Text(); + Matrix matrix = new Matrix(); + Font font = new Font("Helvetica"); + GraphicState graphicState = new GraphicState(); + TextState textState = new TextState(); + + matrix.A = 42; + matrix.D = 22; + matrix.H = 72; + matrix.V = 72; + + TextRun textRun = new TextRun("sample text", font, graphicState, textState, matrix); + text.AddRun(textRun); + + Text text2 = new Text(); + + matrix.A = 30; + matrix.D = 30; + matrix.H = 72; + matrix.V = 288; + + TextRun textRun2 = new TextRun("Text definition provided here", font, graphicState, textState, matrix); + text2.AddRun(textRun2); + + // Containers, Forms and Annotations can be attached to an + // OptionalContentGroup; other content (like Image) can + // be made optional by placing it inside a Container + Container imageContainer = new Container(); + imageContainer.Content = new Content(); + imageContainer.Content.AddElement(image); + + Container imageContainer2 = new Container(); + imageContainer2.Content = new Content(); + imageContainer2.Content.AddElement(image2); + + Container textContainer = new Container(); + textContainer.Content = new Content(); + textContainer.Content.AddElement(text); + + Container textContainer2 = new Container(); + textContainer2.Content = new Content(); + textContainer2.Content.AddElement(text2); + + using (Document newDoc = new Document()) + { + using (Page newPage = newDoc.CreatePage(Document.BeforeFirstPage, pg.MediaBox)) + { + newPage.Content.AddElement(imageContainer); + newPage.Content.AddElement(imageContainer2); + newPage.Content.AddElement(textContainer); + newPage.Content.AddElement(textContainer2); + + // We create new OptionalContentGroups and place them in the OptionalContentConfig.Order array + List ocgs = CreateNewOptionalContentGroups(newDoc, new List { "Rubber Ducky", "PNG Logo", "Example Text", "Text Definition" }); + + AssociateOCGWithContainer(newDoc, ocgs[0], imageContainer); + AssociateOCGWithContainer(newDoc, ocgs[1], imageContainer2); + AssociateOCGWithContainer(newDoc, ocgs[2], textContainer); + AssociateOCGWithContainer(newDoc, ocgs[3], textContainer2); + + newPage.UpdateContent(); + + newDoc.Save(SaveFlags.Full, sOutput); + } + } + } + } + } + } - // We replace the Image with the Container - // (which now holds the image) - pg.Content.RemoveElement(0); - pg.UpdateContent(); + public static List CreateNewOptionalContentGroups(Document doc, List names) + { + List ocgs = new List(); - pg.Content.AddElement(container); - pg.UpdateContent(); + OptionalContentGroup ocg = new OptionalContentGroup(doc, names[0]); + OptionalContentGroup ocg2 = new OptionalContentGroup(doc, names[1]); + OptionalContentGroup ocg3 = new OptionalContentGroup(doc, names[2]); + OptionalContentGroup ocg4 = new OptionalContentGroup(doc, names[3]); - // We create a new OptionalContentGroup and place it in the - // OptionalContentConfig.Order array - OptionalContentGroup ocg = CreateNewOptionalContentGroup(doc, "Rubber Ducky"); + ocgs.Add(ocg); + ocgs.Add(ocg2); + ocgs.Add(ocg3); + ocgs.Add(ocg4); - // Now we associate the Container with the OptionalContentGroup - // via an OptionalContentMembershipDict. Note that we MUST - // update the Page's content afterwards. - AssociateOCGWithContainer(doc, ocg, container); - pg.UpdateContent(); + // Add it to the Order array -- this is required so that it will appear in the 'Layers' panel in a PDF Viewer. + OptionalContentOrderArray order_list = doc.DefaultOptionalContentConfig.Order; - doc.Save(SaveFlags.Full, sOutput); - } - } + OptionalContentOrderArray grouping = new OptionalContentOrderArray(doc, "Image Grouping"); + grouping.Add(new OptionalContentOrderLeaf(ocg)); + grouping.Add(new OptionalContentOrderLeaf(ocg2)); - // Create an OptionalContentGroup with a given name, and add it to the - // default OptionalContentConfig's Order array. - public static OptionalContentGroup CreateNewOptionalContentGroup(Document doc, string name) - { - // Create an OptionalContentGroup - OptionalContentGroup ocg = new OptionalContentGroup(doc, name); + OptionalContentOrderArray grouping2 = new OptionalContentOrderArray(doc, "Text Grouping"); + grouping2.Add(new OptionalContentOrderLeaf(ocg3)); + grouping2.Add(new OptionalContentOrderLeaf(ocg4)); - // Add it to the Order array -- this is required so that the OptionalContentGroup - // will appear in the 'Layers' control panel in a PDF Viewer. It will appear in - // the control panel with the name given in the OptionalContentGroup constructor. - OptionalContentOrderArray order_list = doc.DefaultOptionalContentConfig.Order; - order_list.Insert(order_list.Length, new OptionalContentOrderLeaf(ocg)); + order_list.Insert(order_list.Length, grouping); + order_list.Insert(order_list.Length, grouping2); - return ocg; + return ocgs; } // Associate a Container with an OptionalContentGroup via an OptionalContentMembershipDict. - // This function associates a Containter with a single OptionalContentGroup and uses + // This function associates a Container with a single OptionalContentGroup and uses // a VisibilityPolicy of AnyOn. public static void AssociateOCGWithContainer(Document doc, OptionalContentGroup ocg, Container cont) { @@ -99,9 +156,8 @@ public static void AssociateOCGWithContainer(Document doc, OptionalContentGroup // 'typical' usage; other options can be used to create an 'inverting' layer // (i.e. 'Display this content when the layer is turned OFF'), or to make the // Container's visibility depend on several OptionalContentGroups - OptionalContentMembershipDict ocmd = new OptionalContentMembershipDict(doc, new OptionalContentGroup[] {ocg}, VisibilityPolicy.AnyOn); + OptionalContentMembershipDict ocmd = new OptionalContentMembershipDict(doc, new OptionalContentGroup[] { ocg }, VisibilityPolicy.AnyOn); - // Associate the Container with the OptionalContentMembershipDict cont.OptionalContentMembershipDict = ocmd; } } diff --git a/Samples.sln b/Samples.sln index cfaba70..3783c8e 100644 --- a/Samples.sln +++ b/Samples.sln @@ -180,7 +180,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegexTextSearch", "Text\Reg EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TextExtract", "Text\TextExtract\TextExtract.csproj", "{11C4A647-3DDA-41A5-855C-E14EDF1BFFDE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddDigitalSignature", "Security\AddDigitalSignature\AddDigitalSignature.csproj", "{AB753937-DF3D-4B06-B475-D3B597D32BC5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddDigitalSignatureCMS", "Security\AddDigitalSignatureCMS\AddDigitalSignatureCMS.csproj", "{AB753937-DF3D-4B06-B475-D3B597D32BC5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddDigitalSignatureRFC3161", "Security\AddDigitalSignatureRFC3161\AddDigitalSignatureRFC3161.csproj", "{74FA984E-AB89-475A-9077-9D612DE12AEC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -548,6 +550,10 @@ Global {AB753937-DF3D-4B06-B475-D3B597D32BC5}.Debug|x64.Build.0 = Debug|x64 {AB753937-DF3D-4B06-B475-D3B597D32BC5}.Release|x64.ActiveCfg = Release|x64 {AB753937-DF3D-4B06-B475-D3B597D32BC5}.Release|x64.Build.0 = Release|x64 + {74FA984E-AB89-475A-9077-9D612DE12AEC}.Debug|x64.ActiveCfg = Debug|x64 + {74FA984E-AB89-475A-9077-9D612DE12AEC}.Debug|x64.Build.0 = Debug|x64 + {74FA984E-AB89-475A-9077-9D612DE12AEC}.Release|x64.ActiveCfg = Release|x64 + {74FA984E-AB89-475A-9077-9D612DE12AEC}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Security/AddDigitalSignature/AddDigitalSignature.cs b/Security/AddDigitalSignatureCMS/AddDigitalSignatureCMS.cs similarity index 86% rename from Security/AddDigitalSignature/AddDigitalSignature.cs rename to Security/AddDigitalSignatureCMS/AddDigitalSignatureCMS.cs index cfdd689..e742437 100644 --- a/Security/AddDigitalSignature/AddDigitalSignature.cs +++ b/Security/AddDigitalSignatureCMS/AddDigitalSignatureCMS.cs @@ -5,18 +5,18 @@ /* * - * This sample program demonstrates the use of AddDigitalSignature. + * This sample program demonstrates the use of AddDigitalSignature for CMS signature type. * * Copyright (c) 2025, Datalogics, Inc. All rights reserved. * */ -namespace AddDigitalSignature +namespace AddDigitalSignatureCMS { - class AddDigitalSignature + class AddDigitalSignatureCMS { static void Main(string[] args) { - Console.WriteLine("AddDigitalSignature Sample:"); + Console.WriteLine("AddDigitalSignatureCMS Sample:"); using (new Library()) { @@ -24,7 +24,7 @@ static void Main(string[] args) String sInput = Library.ResourceDirectory + "Sample_Input/SixPages.pdf"; String sLogo = Library.ResourceDirectory + "Sample_Input/ducky_alpha.tif"; - String sOutput = "DigSig-out.pdf"; + String sOutput = "DigSigCMS-out.pdf"; String sDERCert = Library.ResourceDirectory + "Sample_Input/Credentials/DER/RSA_certificate.der"; String sDERKey = Library.ResourceDirectory + "Sample_Input/Credentials/DER/RSA_privKey.der"; @@ -55,6 +55,10 @@ static void Main(string[] args) sigDoc.SetNonPfxSignerCert(sDERCert, 0, CredentialStorageFmt.OnDisk); sigDoc.SetNonPfxPrivateKey(sDERKey, 0, CredentialStorageFmt.OnDisk); + // Set the signature type to be used. + // The available types are defined in the SignatureType enum. Default CMS. + sigDoc.DocSignType = SignatureType.CMS; + // Setup the signer information // (Logo image is optional) sigDoc.SetSignerInfo(sLogo, 0.5F, "John Doe", "Chicago, IL", "Approval", "Datalogics, Inc.", diff --git a/Security/AddDigitalSignature/AddDigitalSignature.csproj b/Security/AddDigitalSignatureCMS/AddDigitalSignatureCMS.csproj similarity index 93% rename from Security/AddDigitalSignature/AddDigitalSignature.csproj rename to Security/AddDigitalSignatureCMS/AddDigitalSignatureCMS.csproj index 866e62e..58f089f 100644 --- a/Security/AddDigitalSignature/AddDigitalSignature.csproj +++ b/Security/AddDigitalSignatureCMS/AddDigitalSignatureCMS.csproj @@ -6,8 +6,8 @@ x64 {AB753937-DF3D-4B06-B475-D3B597D32BC5} Exe - AddDigitalSignature - AddDigitalSignature + AddDigitalSignatureCMS + AddDigitalSignatureCMS v4.7.2 512 true @@ -45,7 +45,7 @@ - + diff --git a/Security/AddDigitalSignature/AddDigitalSignature.sln b/Security/AddDigitalSignatureCMS/AddDigitalSignatureCMS.sln similarity index 91% rename from Security/AddDigitalSignature/AddDigitalSignature.sln rename to Security/AddDigitalSignatureCMS/AddDigitalSignatureCMS.sln index fb572c5..ccaef93 100644 --- a/Security/AddDigitalSignature/AddDigitalSignature.sln +++ b/Security/AddDigitalSignatureCMS/AddDigitalSignatureCMS.sln @@ -2,7 +2,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.13.35818.85 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddDigitalSignature", "AddDigitalSignature.csproj", "{3790CE63-DB43-4F16-8226-BDFEFA25BCDD}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddDigitalSignatureCMS", "AddDigitalSignatureCMS.csproj", "{3790CE63-DB43-4F16-8226-BDFEFA25BCDD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Security/AddDigitalSignature/App.config b/Security/AddDigitalSignatureCMS/App.config similarity index 100% rename from Security/AddDigitalSignature/App.config rename to Security/AddDigitalSignatureCMS/App.config diff --git a/Security/AddDigitalSignatureRFC3161/AddDigitalSignatureRFC3161.cs b/Security/AddDigitalSignatureRFC3161/AddDigitalSignatureRFC3161.cs new file mode 100644 index 0000000..f4f8726 --- /dev/null +++ b/Security/AddDigitalSignatureRFC3161/AddDigitalSignatureRFC3161.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Datalogics.PDFL; + +/* + * + * This sample program demonstrates the use of AddDigitalSignature for RFC3161 timestamp signature type. + * + * Copyright (c) 2025, Datalogics, Inc. All rights reserved. + * + */ +namespace AddDigitalSignatureRFC3161 +{ + class AddDigitalSignatureRFC3161 + { + static void Main(string[] args) + { + Console.WriteLine("AddDigitalSignatureRFC3161 Sample:"); + + using (new Library()) + { + Console.WriteLine("Initialized the library."); + + String sInput = Library.ResourceDirectory + "Sample_Input/CreateAcroForm2h.pdf"; + + String sOutput = "DigSigRFC3161-out.pdf"; + + if (args.Length > 0) + sInput = args[0]; + + if (args.Length > 1) + sOutput = args[1]; + + Console.WriteLine("Input file: " + sInput); + Console.WriteLine("Writing to output: " + sOutput); + + using (Document doc = new Document(sInput)) + { + using (Datalogics.PDFL.SignDoc sigDoc = new Datalogics.PDFL.SignDoc()) + { + // Setup Sign params + sigDoc.FieldID = SignatureFieldID.SearchForFirstUnsignedField; + + // Set signing attributes + sigDoc.DigestCategory = DigestCategory.Sha256; + + // Set the signature type to be used, RFC3161/TimeStamp. + // The available types are defined in the SignatureType enum. Default CMS. + sigDoc.DocSignType = SignatureType.RFC3161; + + // Setup Save params + sigDoc.OutputPath = sOutput; + + // Finally, sign and save the document + sigDoc.AddDigitalSignature(doc); + + Console.WriteLine(); + } + } + } + } + } +} diff --git a/Security/AddDigitalSignatureRFC3161/AddDigitalSignatureRFC3161.csproj b/Security/AddDigitalSignatureRFC3161/AddDigitalSignatureRFC3161.csproj new file mode 100644 index 0000000..41f0a65 --- /dev/null +++ b/Security/AddDigitalSignatureRFC3161/AddDigitalSignatureRFC3161.csproj @@ -0,0 +1,62 @@ + + + + + Debug + x64 + {74FA984E-AB89-475A-9077-9D612DE12AEC} + Exe + AddDigitalSignatureRFC3161 + AddDigitalSignatureRFC3161 + v4.7.2 + 512 + true + true + + + + + x64 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x64 + pdbonly + false + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + 18.* + + + + + + + diff --git a/Security/AddDigitalSignatureRFC3161/AddDigitalSignatureRFC3161.sln b/Security/AddDigitalSignatureRFC3161/AddDigitalSignatureRFC3161.sln new file mode 100644 index 0000000..1ec98b9 --- /dev/null +++ b/Security/AddDigitalSignatureRFC3161/AddDigitalSignatureRFC3161.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35818.85 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddDigitalSignatureRFC3161", "AddDigitalSignatureRFC3161.csproj", "{74FA984E-AB89-475A-9077-9D612DE12AEC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {74FA984E-AB89-475A-9077-9D612DE12AEC}.Debug|x64.ActiveCfg = Debug|x64 + {74FA984E-AB89-475A-9077-9D612DE12AEC}.Debug|x64.Build.0 = Debug|x64 + {74FA984E-AB89-475A-9077-9D612DE12AEC}.Release|x64.ActiveCfg = Release|x64 + {74FA984E-AB89-475A-9077-9D612DE12AEC}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {08DC1B85-4756-4272-B76A-197A8E79394D} + EndGlobalSection +EndGlobal diff --git a/Security/AddDigitalSignatureRFC3161/App.config b/Security/AddDigitalSignatureRFC3161/App.config new file mode 100644 index 0000000..aad6a5e --- /dev/null +++ b/Security/AddDigitalSignatureRFC3161/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Security/README.md b/Security/README.md index 7bf8293..b960e4f 100644 --- a/Security/README.md +++ b/Security/README.md @@ -1,6 +1,9 @@ -## ***AddDigitalSignature*** +## ***AddDigitalSignatureCMS*** Demonstrates adding a digital signature with a logo to a PDF document. +## ***AddDigitalSignatureRFC3161*** +Demonstrates adding an RFC3161 timestamp signature to a PDF document. + ## ***AddRegexRedaction*** Uses a regular expression to find a specified phrase of text in a PDF document and then redacts that text.