Tuesday, December 4, 2007

Getting started with iText - Part 8 (HelloEncrypted)

The next installation in Getting started with iText translates the HelloEncrypted.java example. It demonstrates how to encrypt the top secret "Hello World" document ;)

Source: http://itextdocs.lowagie.com/tutorial/general/
Documentation: See Step 3 for more information
Example: HelloEncrypted.java

First thing I noticed about the java example was that it used a bitwise OR. Not having used bitwise operators in CF before I hit the documentation. First stop was the iText API. It confirmed that PDFWriter.ALLOW_COPY and PDFWriter.ALLOW_PRINTING are primitive int values. The next stop was checking the CF documentation for bitwise functions. It turned up the BitOr function which can be used on a 32-bit signed integer. So I started coding the translation.

But trying to use PDFWriter.ALLOW_COPY generated an error.


  Error Occurred While Processing Request
  Element ALLOW_COPY is undefined in WRITER.


Puzzled I created a PDFWriter object and dumped it so I could view its properties.

<cfscript>
   writer = createObject("java", "com.lowagie.text.pdf.PdfWriter")>
</cfscript>
<cfdump var="#writer#">


The dump showed the class did have similar constants, but the names were different than what was listed in the API. Perhaps earlier versions of iText used different variable names?



Here are the corrected names of the three variables used in the java example. At least for the version of iText that ships with MX7 anyway.


   (API) PDFWriter.ALLOW_COPY (MX7 iText)    PDFWriter.AllowCopy
   (API) PDFWriter.ALLOW_PRINTING (MX7 iText) PDFWriter.AllowPrinting
   (API) PDFWriter.STANDARD_ENCRYPTION_128 (MX7 iText) PDFWriter.STRENGTH128BITS


After substituting the correct variable names, it worked! If you run the attached code it produces an encrypted PDF with the predicatable password: "Hello" ;-)

As always any comments/corrections/suggestions are welcome.

UPDATE: You may notice the code creates a java.lang.String object which is then used to retrieve the string's byte array. This is just a personal preference. It could also be written as:


   #javacast("string", "Hello").getBytes()#


<h1>Hello World Encrypted</h1>
<cfscript>
    savedErrorMessage = "";
    
    // by default outputs to current directory. change as needed
    fullPathToOutputFile = ExpandPath("./HelloEncrypted.pdf");
    
    // step 1: creation of a document-object
    document = createObject("java", "com.lowagie.text.Document").init();

    try {
        // step 2:
        // we create a writer that listens to the document
        // and directs a PDF-stream to a file
        outStream = createObject("java", "java.io.FileOutputStream").init(fullPathToOutputFile);
        writer = createObject("java", "com.lowagie.text.pdf.PdfWriter").getInstance(document, outStream);

        string = createObject("java", "java.lang.String");
        writer.setEncryption( string.init("Hello").getBytes(),
                    string.init("World").getBytes(),
                    BitOr(writer.AllowCopy, writer.AllowPrinting),
                    writer.STRENGTH128BITS);
        
        // step 3: we open the document
        document.open();
    
        // step 4: we add a paragraph to the document
        paragraph = createObject("java", "com.lowagie.text.Paragraph").init("Hello World");
        document.add(paragraph);
        
        WriteOutput("Finished!");
    }
    catch (com.lowagie.text.DocumentException de) {
        savedErrorMessage = de;
    }
    catch (java.io.IOException ioe) {
        savedErrorMessage = ioe;
    }
    // step 5: we close the document
    document.close();
</cfscript>


<!--- show any errors --->
<cfif len(savedErrorMessage) gt 0>
    Error - unable to create document
    <cfdump var="#savedErrorMessage#">
</cfif>

0 comments:

  © Blogger templates The Professional Template by Ourblogtemplates.com 2008

Header image adapted from atomicjeep