views:

324

answers:

2

Hi all,

I'm creating a pdf file using BIRT reporting library. Later I need to digitally sign these files. I'm using iText to digitally sign the document.

The issue I'm facing is, I need to place the signature in different places in different reports. I already have the code to digitally sign the document, now I'm always placing the signature at the bottom of last page in every report.

Eventually I need each report to say where I need to place the signature. Then I've to read the location using iText and then place the signature at that location.

Is this possible to achieve using BIRT and iText

Thanks

+1  A: 

I don't know anything about BIRT, and have only a little familiarity with iText. But maybe this works...

Can BIRT generate the signature box's outline as a regular form field with a given field name? If so, then you should be able to:

  1. Lookup that field by name in iText's AcroFields hashmap, using getField;
  2. Create a new signature using the pdf stamper, and set its geometry based on the values of the old field object; and
  3. Delete the old field using removeField.
Charles Stewart
Thanks for you suggestion, let me check whether BIRT can add a form field to the PDF.
Arun P Johny
+1  A: 

If you're willing to cheat a bit, you can use a link... which BIRT supports according to my little dive into their docs just now.

A link is an annotation. Sadly, iText doesn't support examining annotations at a high level, only generating them, so you'll have to use the low-level object calls.

The code to extract it might look something like this:

// getPageN is looking for a page number, not a page index
PdfDictionary lastPageDict = myReader.getPageN(myReader.getNumberOfPages());

PdfArray annotations = lastPageDict.getAsArray( PdfName.ANNOTS );
PdfArray linkRect = null;
if (annotations != null) {
  int numAnnots = annotations.size();
  for (int i = 0; i < numAnnots; ++i) {
    PdfDictionary annotDict = annotations.getAsDict( i );
    if (annotDict == null) 
      continue; // it'll never happen, unless you're dealing with a Really Messed Up PDF.

    if (PdfName.LINK.equals( annotDict.getAsName( PdfName.SUBTYPE ) )) {
      // if this isn't the only link on the last page, you'll have to check the URL, which
      // is a tad more work.
      linkRect = annotDict.getAsArray( PdfName.RECT );

      // a little sanity check here wouldn't hurt, but I have yet to come across a PDF
      // that was THAT screwed up, and I've seen some Really Messed Up PDFs over the years.

      // and kill the link, it's just there for a placeholder anyway.
      // iText doesn't maintain any extra info on links, so no need for other calls.
      annotations.remove( i ); 
      break;
    }
  }
}

if (linkRect != null) {
  // linkRect is an array, thusly: [ llx, lly, urx, ury ].
  // you could use floats instead, but I wouldn't go with integers.  
  double llx = linkRect.getAsNumber( 0 ).getDoubleValue(); 
  double lly = linkRect.getAsNumber( 1 ).getDoubleValue();
  double urx = linkRect.getAsNumber( 2 ).getDoubleValue();
  double ury = linkRect.getAsNumber( 3 ).getDoubleValue();

  // make your signature
  magic();
}

If BIRT generates some text in the page contents under the link for its visual representation, that's only a minor issue. Your signature should cover it completely.

You're definitely better of if you can generate the signature directly from BIRT in the first place, but my little inspection of their docs didn't exactly fill me with confidence in their PDF customization abilities... despite sitting on top of iText themselves. It's a report generator that happens to be able to produce PDFs... I shouldn't expect too much. `

Edit: If you need to look for the specific URL, you'll want to look at section "12.5.6.5 Link Annotations" of the PDF Reference, which can be found here: http://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf

Mark Storer