I started tinkering with using Flying Saucer to replace cfDocument in
openbluedragon, I don't really have time to keep working on it right now
so I thought I'd post what I accomplished in case others would like to
continue the work, Notes follow and source is attached,

This replacement uses Flying Saucer, aka xhtmlrenderer, available from
https://xhtmlrenderer.dev.java.net, in order to compile it you will need
to build FS from cvs source as I had to contribute a patch to allow
finer grained control of the PDF output encryption, it's been applied to
trunk but they haven't made a release since then.

The hooks for cfdocument are actually still in the openbluedragon source
code, so you have to change the build scripts to bring in the iText and
xhtmlrenderer jars, but not the actual tag parser code, see
src/com/naryx/tagfusion/cfm/tag/tagChecker.java if you want the details
on that, you'll either want to update the path there or place the
attached source file at
src/com/naryx/tagfusion/cfm/document/cfDOCUMENT.java (which is what I'd
recommend)

you'll need xhtmlrenderer and the version of iText it uses (2.0.8 I
think) and you'll need to update your build.xml to include them in the
final build and in the generated war file (There may be a better way to
do this, I was fairly unfamiliar with the use of external libraries in
openbluedragon), look in build.xml for the section <path
id="project.class.build"> and add the iText/flyingsaucer jars there

Yes I know there was some talk of using PDFBox for this purpose, I took
a quick peek at it and didn't like what I saw for some reason, I don't
remember why now, so feel free to discard this mail entirely if you'd
prefer PDFBox

Certain elements that are not supported in the tag attributes, can be
set through css properties, most notably the orientation currently
cannot be set in the attributed because xhtmlrenderer does not allow
that fine grained of a control over the pdf rendered output, it should
however support using css with @page { size: landscape; } to set a
landscape mode.
As well, because xhtmlrenderer supports drawing to a java swing surface,
it should be fairly trivial to support outputting to any image format
supported by the java libraries.

The most important note is that somewhere the paths are screwy.
referencing a uri at "./" will not work as I expected it to, and I never
did sort out exactly where it thought it's paths were, I don't know
enough about the BlueDragon internals to figure out how to resolve paths
properly. so to reference css files or images or files, you'll either
need to fiddle with the paths, or maybe try using external paths.
Someone who knows more about the bluedragon internals should be able to
figure this out without too much trouble.

I wrote this about a month ago over two weekends, and haven't touched it
since, I'm too busy to keep working on it, I'll answer any questions I
can, but if this is going to become any more useful than it is, it needs
to be finished by someone else. I just copied the gpl3 boilerplate from
another file and put my name on it, feel free to fix any issues with it
but please leave my name there.

Hope this is useful to someone, Enjoy :)

- Josh


--~--~---------~--~----~------------~-------~--~----~
Open BlueDragon Public Mailing List
 http://groups.google.com/group/openbd?hl=en
 official blog @ http://blog.openbluedragon.org/
!! save a network - trim replies before posting !!
-~----------~----~----~----~------~----~------~--~---

/*
 *  Copyright (C) 2008 Josh Hayes-Sheen <[EMAIL PROTECTED]>
 *
 *  This file is part of Open BlueDragon (OpenBD) CFML Server Engine.
 *
 *  OpenBD is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  Free Software Foundation,version 3.
 *
 *  OpenBD 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpenBD.  If not, see http://www.gnu.org/licenses/
 *
 *  Additional permission under GNU GPL version 3 section 7
 *
 *  If you modify this Program, or any covered work, by linking or combining
 *  it with any of the JARS listed in the README.txt (or a modified version of
 *  (that library), containing parts covered by the terms of that JAR, the
 *  licensors of this Program grant you additional permission to convey the
 *  resulting work.
 *  README.txt @ http://www.openbluedragon.org/license/README.txt
 *
 *  http://www.openbluedragon.org/
 */


package com.naryx.tagfusion.cfm.document;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.xhtmlrenderer.pdf.PDFEncryption;
import org.xml.sax.SAXException;

import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfWriter;
import com.naryx.tagfusion.cfm.engine.cfBinaryData;
import com.naryx.tagfusion.cfm.engine.cfSession;
import com.naryx.tagfusion.cfm.engine.cfmBadFileException;
import com.naryx.tagfusion.cfm.engine.cfmRunTimeException;
import com.naryx.tagfusion.cfm.engine.variableStore;
import com.naryx.tagfusion.cfm.tag.cfTag;
import com.naryx.tagfusion.cfm.tag.cfTagReturnType;

public class cfDOCUMENT extends cfTag implements Serializable {

        private static final long serialVersionUID = 1L;

        public boolean doesTagHaveEmbeddedPoundSigns() 
        {
                return true;
        }

        public String getEndMarker()
        {
                return "</CFDOCUMENT>";  
        }

        protected void defaultParameters( String _tag ) throws 
cfmBadFileException {
                defaultAttribute( "OVERWRITE", "NO" );
                defaultAttribute( "PAGETYPE", "LETTER" ); // Not yet Supported
                defaultAttribute( "ORIENTATION", "PORTRAIT" ); // Not yet 
Supported
                defaultAttribute( "UNIT", "IN" ); // Not yet Supported
                defaultAttribute( "ENCRYPTION", "NONE" ); // Supports 40, 128 
and new value of AES
                defaultAttribute( "FONTEMBED", "NO" ); // Not yet supported
                defaultAttribute( "BACKGROUNDVISIBLE", "NO" ); // Not yet 
supported
                defaultAttribute( "MIMETYPE", "TEXT/HTML" ); // Not yet 
supported
                parseTagHeader(_tag);
                requiredAttribute( "FORMAT" ); // Only accepts PDF
                // setFlushable( false );
        }

        /* I have to imagine there's a better way to do this :-\ */
        public String getURI(cfSession _Session)
        {
                StringBuilder URIb = new StringBuilder("");
                URIb.append("file://");

                // URIb.append( 
_Session.getQualifiedData(variableStore.CGI_SCOPE).getData("http_host").toString()
 );
                URIb.append( 
_Session.getQualifiedData(variableStore.CGI_SCOPE).getData("context_path").toString()
 + "/");
                return URIb.toString();
        }
        
        public cfTagReturnType render( cfSession _Session ) throws 
cfmRunTimeException 
        {               
                ITextRenderer renderer = new ITextRenderer();
                
                if ( !getDynamic( _Session, "FORMAT" 
).toString().equalsIgnoreCase("PDF") )
                {
                        throw newRunTimeException( "Output format \"" + 
getDynamic( _Session, "FORMAT" ).toString() + "\"is Unsupported!" );
                }
                
            if ( renderToString( _Session ).getOutput().trim().equals("") )
            {
                throw newRunTimeException( "Cannot create a PDF from an empty 
document!" );     
            }
          
                try {
                        DocumentBuilder builder = 
DocumentBuilderFactory.newInstance().newDocumentBuilder();
                        InputStream is = new 
ByteArrayInputStream(renderToString( _Session ).getOutput().getBytes());
                        Document doc = builder.parse( is );

                        renderer.setDocument( doc, getURI(_Session) );
                        
                        renderer.layout();

                        ByteArrayOutputStream mOutputPDF = new 
ByteArrayOutputStream();

                        if ( ( getDynamic( _Session, "ENCRYPTION" 
).toString().equals("128") || getDynamic( _Session, "ENCRYPTION" 
).toString().equals("40") || getDynamic( _Session, "ENCRYPTION" 
).toString().equals("AES") ) || 
                                        containsAttribute("OWNERPASSWORD") ||
                                        containsAttribute("USERPASSWORD") ||
                                        containsAttribute("PERMISSIONS") )
                        {
                                PDFEncryption mEnc = new PDFEncryption();
                                
                                // The password required to make permission 
changes to the document
                                if ( containsAttribute("OWNERPASSWORD") )
                                        mEnc.setOwnerPassword(getDynamic( 
_Session, "OWNERPASSWORD" ).toString().getBytes());
                                else
                                        mEnc.setOwnerPassword(null);
                                
                                // The password required to open the document
                                if ( containsAttribute("USERPASSWORD") )
                                        mEnc.setUserPassword(getDynamic( 
_Session, "USERPASSWORD" ).toString().getBytes());
                                else
                                        mEnc.setUserPassword(null);

                                int PermMask = 0;

                                if ( getDynamic( _Session, "PERMISSIONS" 
).toString().toUpperCase().contains("ALLOWPRINTING") )
                                {
                                        PermMask |= PdfWriter.ALLOW_PRINTING;
                                }
                                if ( getDynamic( _Session, "PERMISSIONS" 
).toString().toUpperCase().contains("ALLOWMODIFYCONTENTS") )
                                {
                                        PermMask |= 
PdfWriter.ALLOW_MODIFY_CONTENTS;
                                }
                                if ( getDynamic( _Session, "PERMISSIONS" 
).toString().toUpperCase().contains("ALLOWCOPY") )
                                {
                                        PermMask |= PdfWriter.ALLOW_COPY;
                                }
                                if ( getDynamic( _Session, "PERMISSIONS" 
).toString().toUpperCase().contains("ALLOWMODIFYANNOTATIONS") )
                                {
                                        PermMask |= 
PdfWriter.ALLOW_MODIFY_ANNOTATIONS;
                                }
                                if ( getDynamic( _Session, "PERMISSIONS" 
).toString().toUpperCase().contains("ALLOWFILLIN") )
                                {
                                        PermMask |= PdfWriter.ALLOW_FILL_IN;
                                }
                                if ( getDynamic( _Session, "PERMISSIONS" 
).toString().toUpperCase().contains("ALLOWSCREENREADERS") )
                                {
                                        PermMask |= 
PdfWriter.ALLOW_SCREENREADERS;
                                }
                                if ( getDynamic( _Session, "PERMISSIONS" 
).toString().toUpperCase().contains("ALLOWASSEMBLY") )
                                {
                                        PermMask |= PdfWriter.ALLOW_ASSEMBLY;
                                }
                                if ( getDynamic( _Session, "PERMISSIONS" 
).toString().toUpperCase().contains("ALLOWDEGRADEDPRINTING") )
                                {
                                        PermMask |= 
PdfWriter.ALLOW_DEGRADED_PRINTING;
                                }

                                // If the user set permissions, set them, 
otherwise just leave the defaults
                                if ( PermMask != 0 )
                                        mEnc.setAllowedPrivileges(PermMask);
                                
                                if ( getDynamic( _Session, "ENCRYPTION" 
).toString().equals("40") )
                                {
                                        
mEnc.setEncryptionType(PdfWriter.STANDARD_ENCRYPTION_40);
                                }
                                else if ( getDynamic( _Session, "ENCRYPTION" 
).toString().equals("128") )
                                {
                                        
mEnc.setEncryptionType(PdfWriter.STANDARD_ENCRYPTION_128);
                                }
                                else if ( getDynamic( _Session, "ENCRYPTION" 
).toString().equals("AES") )
                                {
                                        
mEnc.setEncryptionType(PdfWriter.ENCRYPTION_AES_128);
                                }
                                else if ( containsAttribute("OWNERPASSWORD") || 
containsAttribute("USERPASSWORD") || containsAttribute("PERMISSIONS") )
                                {
                                        // Default to RC40 (The most 
universally compatible PDF encryption scheme) if security attributes are set
                                        // but no encryption type is chosen.
                                        
mEnc.setEncryptionType(PdfWriter.STANDARD_ENCRYPTION_40);
                                }
                                
                                renderer.setPDFEncryption( mEnc );
                        }
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                     
                        renderer.createPDF(mOutputPDF);

                        if ( containsAttribute("FILENAME") ) // Write to the 
Filesystem
                        {
                                File localFile = new File(getDynamic( _Session, 
"FILENAME" ).getString());
                                if ( localFile.exists() && !getDynamic( 
_Session, "OVERWRITE" ).getBoolean() )
                                {
                                        throw new IOException("File \"" + 
localFile.getCanonicalPath() + "\" Already Exists");
                                }
                                FileOutputStream mFile = new 
FileOutputStream(localFile);
                                mFile.write(mOutputPDF.toByteArray());
                                mFile.close();
                        }
                        else if ( containsAttribute("NAME") ) // Store to a 
variable
                        {
                                String NAME = getDynamic( _Session, 
"NAME").getString().trim();
                                if ( NAME.length() == 0 )
                                        throw newRunTimeException( "Invalid 
NAME attribute" );
                                _Session.setData( NAME, new cfBinaryData( 
mOutputPDF.toByteArray() ) );                 
                        }
                        else // Output to the Browser
                        {
                                _Session.resetBuffer();
                                _Session.setContentType( "APPLICATION/PDF" );
                                _Session.write(mOutputPDF.toByteArray());
                                _Session.pageFlush();
                                _Session.abortPageProcessing();
                        }

                } catch (IOException e) {
                        throw newRunTimeException( e.toString() );
                } catch (DocumentException e) {
                        throw newRunTimeException( e.toString() );
                } catch (ParserConfigurationException e) {
                        throw newRunTimeException( e.toString() );
                } catch (SAXException e) {
                        throw newRunTimeException( e.toString() );
                }

                return cfTagReturnType.NORMAL;
        }

}

Reply via email to