Disable extended features with iTextSharp - c#

I have a PDF template with a form with the Extended features enabled. After filling in the fields of this form using iTextSharp, a user with acrobat reader gets the error message:
This document enabled extended features in Adobe Reader. The document has
been changed since it was created and use of extended features is no longer
available. Please contact the author for the original version of this
document.
I googled a bit but all the posts talk about "enabling" extended features, however, I want the form fields to remain disabled and extended features turned off
Here a sample code which I am using:
using (var existingFileStream = new FileStream(fileNameExisting, FileMode.Open))
using (var newFileStream = new FileStream(fileNameNew, FileMode.Create))
{
// Open existing PDF
var pdfReader = new PdfReader(existingFileStream);
// PdfStamper, which will create
var stamper = new PdfStamper(pdfReader, newFileStream);
var form = stamper.AcroFields;
var fieldKeys = form.Fields.Keys;
foreach (string fieldKey in fieldKeys)
{
if (fieldKey.Equals("Retailer Name"))
form.SetField(fieldKey, retailerName);
}
// “Flatten” the form so it wont be editable/usable anymore
stamper.FormFlattening = true;
stamper.Close();
pdfReader.Close();
}

The links here are dead as the iTextPdf web site has been completely revamped. But the answer can be understood without those links, too.
The iText Keyword: Reader enabled PDFs points to the following information:
Submitted by Bruno Lowagie on Fri, 12/31/2010 - 16:37
After filling out my form, my PDF shows the following message: This document enabled extended features in Adobe Reader. The document has been changed since it was created and use of extended features is no longer available. Please contact the author for the original version of this document. How do I avoid this message?
The creator of the form made the document Reader enabled. Reader enabling can only be done using Adobe software. You can avoid this message in two ways:
Remove the usage rights. This will result in a form that is no longer Reader enabled. For instance: if the creator of the document allowed that the filled out form could be saved locally, this will no longer be possible after removing the usage rights.
Fill out the form in append mode. This will result in a bigger file size, but Reader enabling will be preserved.
It also points to the sample ReaderEnabledForm.java (the C#/iTextSharp equivalent of which is ReaderEnabledForm.cs) which shows how to do either.
In your case this amounts to calling
pdfReader.RemoveUsageRights();
right after creating the PdfReader and before creating the PdfStamper.
/**
* Removes any usage rights that this PDF may have. Only Adobe can grant usage rights
* and any PDF modification with iText will invalidate them. Invalidated usage rights may
* confuse Acrobat and it's advisabe to remove them altogether.
*/
public void RemoveUsageRights()

Fill out the form in append mode by using the PdfStamper constractor overload
// PdfStamper, which will create
var stamper = new PdfStamper(pdfReader, fileStream, '\0', true);

Related

iText7 usage rights and Adobe Reader

I'm revisiting some old code in an attempt to get this working again. I'm using the code from the iText KB here -> https://kb.itextpdf.com/home/it7kb/faq/how-to-fill-xfa-form-using-itext-without-breaking-usage-rights.
It seems even using that it somehow still breaks the pdf and not then editable with Adobe Reader. Last time I couldn't post the form but have now managed to strip out any important stuff so at least someone can test...hopefully.
I did create a super basic form in Livecycle and reader enable it in Acrobat DC and using the code below it worked fine, yet for some reason this form always breaks.
Here is the code I'm using.
String source = #"D:\Temp\SVTESTx.pdf";
String dest = #"D:\Temp\SVAx.PDF";
PdfReader preader = new PdfReader(source);
PdfDocument pdfDoc=new PdfDocument(preader, new PdfWriter(dest), new StampingProperties().UseAppendMode());
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true);
XfaForm xfa = form.GetXfaForm();
xfa.FillXfaForm(new FileStream(#"D:\Temp\SVTEST.xml", FileMode.Open, FileAccess.Read));
xfa.Write(pdfDoc);
pdfDoc.Close();
The files in question are here (for the non-working PDF) -> https://drive.google.com/drive/folders/1MET19PUubd-J9D4fbzkX1KJAUbn0aMCZ?usp=sharing
Cheers

iTextSharp checkbox has value but is not visible as checked

I need to edit my PDF file using iTextSharp. I have a radio button and checkbox as described below.
I want to have the following: if I put a check mark on the radio button, then the checkbox must be visible as checked.
In the code, the radio button has a value but when I open the PDF file for the first time, the checkbox is not checked.
When I again put a check mark in the radio button then it turns visible.
Here is my code;
PdfReader pdfReader = new PdfReader(pdfTemplate);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.OpenOrCreate));
AcroFields pdfFormFields = pdfStamper.AcroFields;
pdfFormFields.SetField("4a.0", "1"); // radio button
pdfFormFields.SetField("4a.1", "1"); // checkbox
pdfFormFields.SetField("4a.2", "2010"); // text box
There are both issues in the OP's code causing issues independent of the PDF, and special properties of the PDF causing issues specific to the PDF.
PDF independent issues
Closing the PdfStamper
The code provided by the OP does not close the PdfStamper. This is required though, without closing the stamper important information will not be written:
...
pdfStamper.Close();
I assume, though, the OP does close the stamper but merely forgot to copy this line into his question, as the errors I observe without closing the stamper are different.
Inappropriate FileMode
The OP uses new FileStream(newFile, FileMode.OpenOrCreate) to create the file output stream. The file mode OpenOrCreate is documented as:
// Summary:
// Specifies that the operating system should open a file if it exists; otherwise,
// a new file should be created. If the file is opened with FileAccess.Read,
// System.Security.Permissions.FileIOPermissionAccess.Read permission is required.
// If the file access is FileAccess.Write, System.Security.Permissions.FileIOPermissionAccess.Write
// permission is required. If the file is opened with FileAccess.ReadWrite,
// both System.Security.Permissions.FileIOPermissionAccess.Read and System.Security.Permissions.FileIOPermissionAccess.Write
// permissions are required.
OpenOrCreate = 4,
Thus, if newFile already exists, the stamper writes into this file, and if the file the stamper creates is shorter than the formerly existing file, an end piece of that former content remains and effectively makes the PDF invalid.
So please use FileMode.Create instead which is documented as:
// Summary:
// Specifies that the operating system should create a new file. If the file
// already exists, it will be overwritten. This requires System.Security.Permissions.FileIOPermissionAccess.Write
// permission. FileMode.Create is equivalent to requesting that if the file
// does not exist, use System.IO.FileMode.CreateNew; otherwise, use System.IO.FileMode.Truncate.
// If the file already exists but is a hidden file, an System.UnauthorizedAccessException
// exception is thrown.
Create = 2,
Append mode
The OP's code does not use the stamper in append mode. For previously signed documents this causes signatures to break. In case of the document the OP shared there indeed is a signature, a so-called usage rights signature. Thus, when opening the PDF again, Adobe Reader shows:
So please use append mode (or throw away the usage rights signature altogether):
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.Create), '\0', true);
PDF dependent issues
PDF not exactly following PDF specification
As already remarked in a comment to the question:
The form abuses PDF somewhat. Both 4a.0 and 4a.1 are button fields which have no Ff (Field Flags) entry, i.e. for both fields the flags value is the default 0, which implies that both button fields are checkbox fields as neither the Pushbutton nor the Radio flag is set. But both behave like radio buttons by having multiple kids which in addition to Off know no common appearance states. Such use of PDF features is a hindrance for interoperability.
But iText has no problems with this. Still, the PDF should be fixed.
Hidden values
This is the section of the PDF in question:
When executing the OP's code one sees that the top element of 4a.0 is marked but one sees no difference in the sub-fields 4a.1 or 4a.2.
The cause of this is that while the top level elements (radio buttons in 4a.0) always are visible, the dependent elements 4a.1, 4a.2, and 4a.3 (and similarly also the elements dependent on the other top level radio button choices) in the OP's file are flagged as hidden, so their value is not shown.
In a PDF viewer the hidden flag of the dependent fields are reset by a JavaScript action of the associated top level radio button when it is selected. Thus, the dependent field values become visible.
iTextSharp, on the other hand, does not contain a JavaScript engine to execute such actions. Thus, those fields remain hidden.
So please not only set the field value but also reset the associated hidden flags:
pdfFormFields.SetField("4a.1", "1"); // checkbox
pdfFormFields.SetFieldProperty("4a.1", "clrflags", 2, null);
pdfFormFields.SetField("4a.2", "2010"); // text box
pdfFormFields.SetFieldProperty("4a.2", "clrflags", 2, null);
All changes applied
The source with all changes is this:
PdfReader pdfReader = new PdfReader(pdfTemplate);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.Create), '\0', true);
AcroFields pdfFormFields = pdfStamper.AcroFields;
pdfFormFields.SetField("4a.0", "1"); // radio button
pdfFormFields.SetField("4a.1", "1"); // checkbox
pdfFormFields.SetFieldProperty("4a.1", "clrflags", 2, null);
pdfFormFields.SetField("4a.2", "2010"); // text box
pdfFormFields.SetFieldProperty("4a.2", "clrflags", 2, null);
pdfStamper.Close();
and the result looks like this:

AmyuniPDF prints PDF document in wrong font (special characters)

I am using Amyuni PDF Creator .Net to print PDF using a Windows service.
Windows service is running under Local System user account. When I tried to print using above library, it prints the PDF in wrong font. See the attachment (Wrong font in PDF printing).
This issue persists with only some of the printers such as Brother MFC-8890DW Printer.
But for the same printer with above windows service, it prints the PDF properly when unchecked the Enable advanced printing features setting in above printer Properties. See the attachment (Disable Advanced printing features).
using (FileStream file1 = new FileStream(pdfFile, FileMode.Open, FileAccess.Read))
{
using (IacDocument doc1 = new IacDocument())
{
doc1.Open(file1, string.Empty);
doc1.Copies = 1;
bool printed = doc1.Print(printer, false);
}
}
But same windows service prints PDF correctly for some other printers such as HP LaserJet P1005 either Enable advanced printing features checked or unchecked.
Without having access to the same printer that you are using it is hard to know exactly what is happening. My best guess would be that the driver of this printer has issues dealing with process-level fonts (those that are registered using the GDI function AddFontResourceEx) when "Enable advanced printing features" is checked. This is how Amyuni PDF Creator uses fonts embedded in the PDF file, which is the case for the file that you have presented.
A possible workaround for this could be to use the attribute "PrintAsImage" of the Document class.
The code would look like this:
//set license key This is needed only with licensed version
acPDFCreatorLib.SetLicenseKey("your company", "your activation code");
//Create a new document instance
Amyuni.PDFCreator.IacDocument doc = new Amyuni.PDFCreator.IacDocument(null);
doc.AttributeByName("PrintAsImage").Value =1;
//Open the file here (...)
//Print to default printer
pdfCreator1.Document.Print("", false);
Another alternative would be to save your file as xps using Amyuni PDF Creator then send the xps file to the printer:
// Create print server and print queue.
LocalPrintServer localPrintServer = new LocalPrintServer();
PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue();
defaultPrintQueue.AddJob("my document", "c:\\temp\\mytempfile.xps", true);
Disclaimer: I work for Amyuni Technologies.

Fill PDF Form with Itextsharp

I am trying to fill up a form with ITextsharp, and trying out the following code to get all the fields in the pdf:
string pdfTemplate = #"c:\Temp\questionnaire.pdf";
PdfReader pdfReader = new PdfReader(pdfTemplate);
StringBuilder sb = new StringBuilder();
foreach (var de in pdfReader.AcroFields.Fields)
{
sb.Append(de.Key.ToString() + Environment.NewLine);
}
But the foreach loop is always null count. Do I need to do something to file itself as I have tried the example from here and it works fine... this is an example of pdf I am trying to fill
any ideas?
Edit ::
As it turned out, the PDF "form" to fill in actually wasn't a form (in PDF terms) at all. Thus, your have two choices:
You add the text to the page contents directly using hardcoded or configured "field" positions and dimensions as described by #tschmit007 in comments to his answer.
You add actual PDF form fields to your PDF to generate a true PDF form which you take as template to fill in later.
You can add actual form fields either using some graphical tool allowing that, e.g. Adobe Acrobat, or you can use iText(Sharp). Have a look at chapter 8 of iText in Action — 2nd Edition and the samples available here for Java and here for .Net.
Those samples mostly add form fields to newly generated PDF documents. You can virtually use the same code, though, for adding form fields to a PdfStamper which exposes its inner PdfWriter using stamper.getWriter() in Java and the stamper.Writer in C#. Instead of writer.addAnnotation(field) you have to use stamper.addAnnotation(field, page), though.
try:
using (FileStream outFile = new FileStream("result.pdf", FileMode.Create)) {
PdfReader pdfReader = new PdfReader("file.pdf");
PdfStamper pdfStamper = new PdfStamper(pdfReader, outFile);
AcroFields fields = pdfStamper.AcroFields;
//rest of the code here
//fields.SetField("n°1", "value");
//...
pdfStamper.Close();
pdfReader.Close();
}

Using iText (iTextSharp) to populate XFA form fields in PDF?

I need to populate XFA form fields in a PDF (created with Adobe LiveCycle Designer). We're attempting to use iText (actually iTextSharp with C#) to parse the PDF, populate the XFA fields and then save the modified PDF back out.
All the examples I can find with iText (very few iTextSharp examples) talk about modifying AcroForm fields. This PDF does NOT have AcroForm fields and uses XFA only.
Pointers to any non-standard resources would be helpful (I've already done the requisite Googling on the topic and haven't found anything useful).
Code examples here would be awesome from anyone who has actually done what I'm trying to do.
If you can get a data packet into the PDF, the XFA runtime in Acrobat would populate those fields with the data in the data packet.
If you want to see what one of these looks like, create a form in LiveCycle Designer (comes with Acrobat Pro), add some fields to it, and save it as a dynamic PDF. Open the form in Acrobat and type some values into the fields and save it.
Open the PDF with a tool that lets you peer at the PDF data and you'll find /Catalog/AcroForm/XFA a stream that has an <xfa:datasets> packet with the values you typed. That's what you'll need to create yourself and insert into the PDF.
The XDP spec includes a description of the data packet and the merge algorithm. You can find it here:
http://partners.adobe.com/public/developer/xml/index_arch.html
Alternately, you buy the LiveCycle server from Adobe which lets you do all this programmatically in a number of ways including through web service calls.
using (FileStream existingPdf = new FileStream("existing.pdf", FileMode.Open))
using (FileStream sourceXml = new FileStream("source.xml", FileMode.Open))
using (FileStream newPdf = new FileStream("new.pdf", FileMode.Create))
{
// Open existing PDF
PdfReader pdfReader = new PdfReader(existingPdf);
// PdfStamper, which will create
PdfStamper stamper = new PdfStamper(pdfReader, newPdf);
stamper.AcroFields.Xfa.FillXfaForm(sourceXml);
stamper.Close();
pdfReader.Close();
}
iTextSharp can work with XFA. To remove all doubts, please take a look at sample on iText website:
http://itextpdf.com/examples/iia.php?id=165
I have the same issue and I think I found the solution. I am using Powershell to inspect the pdf object.
Load the iTextSharp DLL.
Add-Type -Path "C:\Users\micah\Desktop\itextsharp.dll"
Load the PDF into a variable:
$PDF = New-Object iTextSharp.text.pdf.pdfreader -ArgumentList "C:\Users\micah\Desktop\test.pdf"
Inspect this object:
$PDF.AcroFields.XFA.DomDocument.XDP.DataSets.Data.TopMostSubForm | Get-Member
What you SHOULD see, is that all your fields on your PDF are in this object as a property.
You can get a quick view of all your fields like this:
$PDF.AcroFields.XFA.DomDocument.XDP.DataSets.Data.TopMostSubForm | Select-Object -Property "*"
That should be the magic ticket. This location is both fields from the original form AND the XFA portion of the form.
It says that in the book because itext does not do this. Can you convert your PDF?

Categories

Resources