Java tutorial
/** * * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * **/ package lucee.runtime.tag; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set; import lucee.commons.io.IOUtil; import lucee.commons.io.res.Resource; import lucee.commons.io.res.filter.ExtensionResourceFilter; import lucee.commons.io.res.filter.ResourceFilter; import lucee.commons.io.res.util.ResourceUtil; import lucee.commons.io.res.util.WildCardFilter; import lucee.commons.lang.StringUtil; import lucee.runtime.exp.ApplicationException; import lucee.runtime.exp.CasterException; import lucee.runtime.exp.ExpressionException; import lucee.runtime.exp.PageException; import lucee.runtime.ext.tag.BodyTagImpl; import lucee.runtime.op.Caster; import lucee.runtime.op.Decision; import lucee.runtime.text.pdf.PDFDocument; import lucee.runtime.text.pdf.PDFUtil; import lucee.runtime.type.Array; import lucee.runtime.type.Collection.Key; import lucee.runtime.type.Struct; import lucee.runtime.type.util.KeyConstants; import lucee.runtime.type.util.ListUtil; import org.apache.oro.text.regex.MalformedPatternException; import org.pdfbox.exceptions.CryptographyException; import org.pdfbox.exceptions.InvalidPasswordException; import com.lowagie.text.DocumentException; import com.lowagie.text.Image; import com.lowagie.text.pdf.PdfContentByte; import com.lowagie.text.pdf.PdfGState; import com.lowagie.text.pdf.PdfImportedPage; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.PdfStamper; import com.lowagie.text.pdf.PdfWriter; import com.lowagie.text.pdf.SimpleBookmark; public class PDF extends BodyTagImpl { private static final int ACTION_ADD_WATERMARK = 0; private static final int ACTION_DELETE_PAGES = 1; private static final int ACTION_GET_INFO = 2; private static final int ACTION_MERGE = 3; private static final int ACTION_PROCESSDDX = 5; private static final int ACTION_PROTECT = 5; private static final int ACTION_READ = 6; private static final int ACTION_REMOVE_WATERMARK = 7; private static final int ACTION_SET_INFO = 8; private static final int ACTION_THUMBNAIL = 9; private static final int ACTION_WRITE = 10; private static final int ACTION_EXTRACT_TEXT = 11; private static final String FORMAT_JPG = "jpg"; private static final String FORMAT_TIFF = "tiff"; private static final String FORMAT_PNG = "png"; private static final int ORDER_TIME = 0; private static final int ORDER_NAME = 1; private static final int RESOLUTION_HIGH = 0; private static final int RESOLUTION_LOW = 1; private static final int SAVE_OPTION_FULL = 0; private static final int SAVE_OPTION_INCREMENTAL = 1; private static final int SAVE_OPTION_LINEAR = 2; private static final int TYPE_STRING = 1; private static final int TYPE_XML = 2; private static final ExtensionResourceFilter PDF_FILTER = new ExtensionResourceFilter("pdf"); private static final int UNDEFINED = Integer.MIN_VALUE; private int action = ACTION_PROCESSDDX; private boolean ascending = false; private Object copyFrom = null; private String ddxFile = null; private Resource destination = null; private Resource directory = null; private int encrypt = PDFUtil.ENCRYPT_RC4_128; private boolean flatten = false; private boolean foreground = false; private String format = FORMAT_JPG; private Object image = null; private Struct info = null; private Struct inputFiles = null; private Struct outputFiles = null; private boolean isBase64 = false; private boolean keepBookmark = false; private String name = null; private String newOwnerPassword = null; private String newUserPassword = null; private float opacity = 0.3F; private int order = ORDER_TIME; private boolean overwrite = false; private String pages = null; private String password = null; private int permissions = 0; private String position = null; private int resolution = RESOLUTION_HIGH; private float rotation = 0; private int saveOption = SAVE_OPTION_FULL; private int scale = 25; private boolean showOnPrint = false; private Object source = null; private boolean stopOnError = false; private boolean transparent = false; private char version = 0; private java.util.List<PDFParamBean> params; private ResourceFilter filter = null; private String imagePrefix = null; private int type = TYPE_XML; @Override public void release() { super.release(); action = ACTION_PROCESSDDX; ascending = false; copyFrom = null; ddxFile = null; destination = null; directory = null; encrypt = PDFUtil.ENCRYPT_RC4_128; flatten = false; foreground = false; format = FORMAT_JPG; image = null; info = null; inputFiles = null; outputFiles = null; isBase64 = false; keepBookmark = false; name = null; newOwnerPassword = null; newUserPassword = null; opacity = 0.3F; order = ORDER_TIME; overwrite = false; pages = null; password = null; permissions = 0; position = null; resolution = RESOLUTION_HIGH; rotation = 0; saveOption = SAVE_OPTION_FULL; scale = 25; showOnPrint = false; source = null; stopOnError = false; transparent = false; version = 0; params = null; filter = null; imagePrefix = null; type = TYPE_XML; } /** * @param imagePrefix the imagePrefix to set */ public void setImageprefix(String imagePrefix) { this.imagePrefix = imagePrefix; } /** * @param action the action to set * @throws ApplicationException */ public void setAction(String strAction) throws ApplicationException { strAction = StringUtil.toLowerCase(strAction.trim()); if ("addwatermark".equals(strAction)) action = ACTION_ADD_WATERMARK; else if ("add-watermark".equals(strAction)) action = ACTION_ADD_WATERMARK; else if ("add_watermark".equals(strAction)) action = ACTION_ADD_WATERMARK; else if ("deletepages".equals(strAction)) action = ACTION_DELETE_PAGES; else if ("delete-pages".equals(strAction)) action = ACTION_DELETE_PAGES; else if ("delete_pages".equals(strAction)) action = ACTION_DELETE_PAGES; else if ("deletepage".equals(strAction)) action = ACTION_DELETE_PAGES; else if ("delete-page".equals(strAction)) action = ACTION_DELETE_PAGES; else if ("delete_page".equals(strAction)) action = ACTION_DELETE_PAGES; else if ("getinfo".equals(strAction)) action = ACTION_GET_INFO; else if ("get-info".equals(strAction)) action = ACTION_GET_INFO; else if ("get_info".equals(strAction)) action = ACTION_GET_INFO; else if ("merge".equals(strAction)) action = ACTION_MERGE; //else if("processddx".equals(strAction)) action=ACTION_PROCESSDDX; //else if("process-ddx".equals(strAction)) action=ACTION_PROCESSDDX; //else if("process_ddx".equals(strAction)) action=ACTION_PROCESSDDX; else if ("protect".equals(strAction)) action = ACTION_PROTECT; else if ("read".equals(strAction)) action = ACTION_READ; else if ("removewatermark".equals(strAction)) action = ACTION_REMOVE_WATERMARK; else if ("removewater-mark".equals(strAction)) action = ACTION_REMOVE_WATERMARK; else if ("removewater_mark".equals(strAction)) action = ACTION_REMOVE_WATERMARK; else if ("setinfo".equals(strAction)) action = ACTION_SET_INFO; else if ("set-info".equals(strAction)) action = ACTION_SET_INFO; else if ("set_info".equals(strAction)) action = ACTION_SET_INFO; else if ("thumbnail".equals(strAction)) action = ACTION_THUMBNAIL; else if ("write".equals(strAction)) action = ACTION_WRITE; else if ("extracttext".equals(strAction)) action = ACTION_EXTRACT_TEXT; else if ("extract-text".equals(strAction)) action = ACTION_EXTRACT_TEXT; else if ("extract_text".equals(strAction)) action = ACTION_EXTRACT_TEXT; else throw new ApplicationException("invalid action definition [" + strAction + "], valid actions definitions are " + "[addWatermark,deletePages,getInfo,merge,protect,read,removeWatermark,setInfo,thumbnail,write]"); } public void setType(String strType) throws ApplicationException { strType = StringUtil.toLowerCase(strType.trim()); if ("string".equals(strType)) type = TYPE_STRING; else if ("text".equals(strType)) type = TYPE_STRING; else if ("plain".equals(strType)) type = TYPE_STRING; else if ("xml".equals(strType)) type = TYPE_XML; else throw new ApplicationException( "invalid type definition [" + strType + "], valid type definitions are " + "[string,xml]"); } /** * sets a filter pattern * @param pattern * @throws PageException **/ public void setFilter(String pattern) throws PageException { if (pattern.trim().length() > 0) { try { this.filter = new WildCardFilter(pattern); } catch (MalformedPatternException e) { throw Caster.toPageException(e); } } } /** * @param ascending the ascending to set */ public void setAscending(boolean ascending) { this.ascending = ascending; } /** * @param copyFrom the copyFrom to set * @throws ExpressionException */ public void setCopyfrom(Object copyFrom) throws ExpressionException { this.copyFrom = copyFrom;//ResourceUtil.toResourceExisting(pageContext, copyFrom); } /** * @param ddxFile the ddxFile to set */ public void setDdxfile(String ddxFile) { this.ddxFile = ddxFile;// MUST } /** * @param destination the destination to set */ public void setDestination(String destination) { this.destination = ResourceUtil.toResourceNotExisting(pageContext, destination); } /** * @param directory the directory to set * @throws ExpressionException */ public void setDirectory(String directory) throws ExpressionException { this.directory = ResourceUtil.toResourceExisting(pageContext, directory); } /** * @param encrypt the encrypt to set * @throws ApplicationException */ public void setEncrypt(String strEncrypt) throws ApplicationException { strEncrypt = StringUtil.toLowerCase(strEncrypt.trim()); if ("aes128".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_AES_128; else if ("aes-128".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_AES_128; else if ("aes_128".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_AES_128; else if ("none".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_NONE; else if ("".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_NONE; else if ("rc4128".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_RC4_128; else if ("rc4-128".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_RC4_128; else if ("rc4_128".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_RC4_128; else if ("rc4128m".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_RC4_128M; else if ("rc4-128m".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_RC4_128M; else if ("rc4_128m".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_RC4_128M; else if ("rc440".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_RC4_40; else if ("rc4-40".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_RC4_40; else if ("rc4_40".equals(strEncrypt)) encrypt = PDFUtil.ENCRYPT_RC4_40; else throw new ApplicationException("invalid encrypt definition [" + strEncrypt + "], valid encrypt definitions are " + "[aes_128,none,rc4_128,rc4_128m,rc4_40]"); } /** * @param flatten the flatten to set */ public void setFlatten(boolean flatten) { this.flatten = flatten; } /** * @param foreground the foreground to set */ public void setForeground(boolean foreground) { this.foreground = foreground; } /** * @param format the format to set * @throws ApplicationException */ public void setFormat(String strFormat) throws ApplicationException { strFormat = StringUtil.toLowerCase(strFormat.trim()); if ("jpg".equals(strFormat)) format = FORMAT_JPG; else if ("jpeg".equals(strFormat)) format = FORMAT_JPG; else if ("jpe".equals(strFormat)) format = FORMAT_JPG; else if ("tiff".equals(strFormat)) format = FORMAT_TIFF; else if ("tif".equals(strFormat)) format = FORMAT_TIFF; else if ("png".equals(strFormat)) format = FORMAT_PNG; else throw new ApplicationException("invalid format definition [" + strFormat + "], valid format definitions are " + "[jpg,tiff,png]"); } /** * @param image the image to set */ public void setImage(Object image) { this.image = image;// MUST } /** * @param prefix the prefix to set */ public void setPrefix(String prefix) { this.imagePrefix = prefix; } /** * @param info the info to set */ public void setInfo(Struct info) { this.info = info; } /** * @param inputFiles the inputFiles to set */ public void setInputfiles(Struct inputFiles) { this.inputFiles = inputFiles; } /** * @param outputFiles the outputFiles to set */ public void setOutputfiles(Struct outputFiles) { this.outputFiles = outputFiles; } /** * @param isBase64 the isBase64 to set */ public void setIsbase64(boolean isBase64) { this.isBase64 = isBase64; } /** * @param keepBookmark the keepBookmark to set */ public void setKeepbookmark(boolean keepBookmark) { this.keepBookmark = keepBookmark; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @param newOwnerPassword the newOwnerPassword to set */ public void setNewownerpassword(String newOwnerPassword) { this.newOwnerPassword = newOwnerPassword; } /** * @param newUserPassword the newUserPassword to set */ public void setNewuserpassword(String newUserPassword) { this.newUserPassword = newUserPassword; } /** * @param opacity the opacity to set * @throws ApplicationException */ public void setOpacity(double opacity) throws ApplicationException { if (opacity < 0 || opacity > 10) throw new ApplicationException("invalid opacity definition [" + Caster.toString(opacity) + "], value should be in range from 0 to 10"); this.opacity = (float) (opacity / 10); } /** * @param order the order to set * @throws ApplicationException */ public void setOrder(String strOrder) throws ApplicationException { strOrder = StringUtil.toLowerCase(strOrder.trim()); if ("name".equals(strOrder)) order = ORDER_NAME; else if ("time".equals(strOrder)) order = ORDER_TIME; else throw new ApplicationException( "invalid order definition [" + strOrder + "], valid order definitions are " + "[name,time]"); } /** * @param overwrite the overwrite to set */ public void setOverwrite(boolean overwrite) { this.overwrite = overwrite; } /** * @param pages the pages to set */ public void setPages(String pages) { this.pages = pages; } /** * @param password the password to set */ public void setPassword(String password) { this.password = password; } /** * @param permissions the permissions to set * @throws PageException */ public void setPermissions(String strPermissions) throws PageException { permissions = PDFUtil.toPermissions(strPermissions); } /** * @param position the position to set */ public void setPosition(String position) { this.position = position;//MUST } /** * @param resolution the resolution to set * @throws ApplicationException */ public void setResolution(String strResolution) throws ApplicationException { strResolution = StringUtil.toLowerCase(strResolution.trim()); if ("low".equals(strResolution)) resolution = RESOLUTION_LOW; else if ("high".equals(strResolution)) resolution = RESOLUTION_HIGH; else throw new ApplicationException("invalid resolution definition [" + strResolution + "], valid resolution definitions are " + "[low,high]"); } /** * @param rotation the rotation to set */ public void setRotation(double rotation) { rotation = rotation % 360D; //rotation=rotation/360*6.28318525; this.rotation = (float) rotation; } /** * @param saveOption the saveOption to set * @throws ApplicationException */ public void setSaveoption(String strSaveOption) throws ApplicationException { strSaveOption = StringUtil.toLowerCase(strSaveOption.trim()); if ("full".equals(strSaveOption)) saveOption = SAVE_OPTION_FULL; else if ("incremental".equals(strSaveOption)) saveOption = SAVE_OPTION_INCREMENTAL; else if ("linear".equals(strSaveOption)) saveOption = SAVE_OPTION_LINEAR; else throw new ApplicationException("invalid saveOption definition [" + strSaveOption + "], valid saveOption definitions are " + "[full,linear,incremental]"); } /** * @param scale the scale to set * @throws ApplicationException */ public void setScale(double scale) throws ApplicationException { //if(scale<1 || scale>1000) this check is now done inside PDF2IMage implementation // throw new ApplicationException("invalid scale definition ["+Caster.toString(scale)+"], value should be in range from 1 to 100"); this.scale = (int) scale; } /** * @param showOnPrint the showOnPrint to set */ public void setShowonprint(boolean showOnPrint) { this.showOnPrint = showOnPrint; } /** * @param source the source to set */ public void setSource(Object source) { this.source = source; } /** * @param stopOnError the stopOnError to set */ public void setStoponerror(boolean stopOnError) { this.stopOnError = stopOnError; } /** * @param transparent the transparent to set */ public void setTransparent(boolean transparent) { this.transparent = transparent; } /** * @param version the version to set * @throws ApplicationException */ public void setVersion(double version) throws ApplicationException { if (1.1 == version) this.version = '1'; else if (1.2 == version) this.version = PdfWriter.VERSION_1_2; else if (1.3 == version) this.version = PdfWriter.VERSION_1_3; else if (1.4 == version) this.version = PdfWriter.VERSION_1_4; else if (1.5 == version) this.version = PdfWriter.VERSION_1_5; else if (1.6 == version) this.version = PdfWriter.VERSION_1_6; else throw new ApplicationException("invalid version definition [" + Caster.toString(version) + "], valid version definitions are " + "[1.1, 1.2, 1.3, 1.4, 1.5, 1.6]"); } @Override public int doStartTag() throws PageException { // RR SerialNumber sn = pageContext.getConfig().getSerialNumber(); //if(sn.getVersion()==SerialNumber.VERSION_COMMUNITY) // throw new SecurityException("no access to this functionality with the "+sn.getStringVersion()+" version of lucee"); return EVAL_BODY_BUFFERED; } @Override public void doInitBody() { } @Override public int doAfterBody() { return SKIP_BODY; } @Override public int doEndTag() throws PageException { try { if (ACTION_ADD_WATERMARK == action) doActionAddWatermark(); else if (ACTION_REMOVE_WATERMARK == action) doActionRemoveWatermark(); else if (ACTION_READ == action) doActionRead(); else if (ACTION_WRITE == action) doActionWrite(); else if (ACTION_GET_INFO == action) doActionGetInfo(); else if (ACTION_SET_INFO == action) doActionSetInfo(); else if (ACTION_MERGE == action) doActionMerge(); else if (ACTION_DELETE_PAGES == action) doActionDeletePages(); else if (ACTION_PROTECT == action) doActionProtect(); else if (ACTION_THUMBNAIL == action) doActionThumbnail(); else if (ACTION_EXTRACT_TEXT == action) { if (true) throw new ApplicationException( "not supported yet, see https://issues.jboss.org/browse/LUCEE-1559"); doActionExtractText(); } //else if(ACTION_PROCESSDDX==action) throw new ApplicationException("action [processddx] not supported"); } catch (Exception e) { throw Caster.toPageException(e); } return EVAL_PAGE; } private void doActionWrite() throws PageException, IOException, DocumentException { required("pdf", "write", "source", source); required("pdf", "write", "destination", destination); if (destination.exists() && !overwrite) throw new ApplicationException("destination file [" + destination + "] already exists"); PDFDocument doc = toPDFDocument(source, password, null); //PdfReader pr = doc.getPdfReader(); // output boolean destIsSource = doc.getResource() != null && destination.equals(doc.getResource()); OutputStream os = null; if (destIsSource) { os = new ByteArrayOutputStream(); } else if (destination != null) { os = destination.getOutputStream(); } try { PDFUtil.concat(new PDFDocument[] { doc }, os, true, true, true, version); } finally { IOUtil.closeEL(os); if (os instanceof ByteArrayOutputStream) { if (destination != null) IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray()), destination, true);// MUST overwrite } } /* // flatten = "yes|no" // must saveOption = "linear|incremental|full" */ } private void doActionThumbnail() throws PageException, IOException, DocumentException { required("pdf", "thumbnail", "source", source); PDFDocument doc = toPDFDocument(source, password, null); PdfReader pr = doc.getPdfReader(); boolean isEnc = pr.isEncrypted(); pr.close(); if (isEnc) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); //PDFUtil.concat(new PDFDocument[]{doc}, baos, true, true, true, (char)0); PDFUtil.encrypt(doc, baos, null, null, 0, PDFUtil.ENCRYPT_NONE); baos.close(); doc = new PDFDocument(baos.toByteArray(), doc.getResource(), null); } doc.setPages(pages); // scale if (scale < 1) throw new ApplicationException("value of attribute scale [" + scale + "] should be at least 1"); // destination if (destination == null) destination = ResourceUtil.toResourceNotExisting(pageContext, "thumbnails"); // imagePrefix if (imagePrefix == null) { Resource res = doc.getResource(); if (res != null) { String n = res.getName(); int index = n.lastIndexOf('.'); if (index != -1) imagePrefix = n.substring(0, index); else imagePrefix = n; } else imagePrefix = "memory"; } // MUST password PDFUtil.writeImages(doc.getRaw(), doc.getPages(), destination, imagePrefix, format, scale, overwrite, resolution == RESOLUTION_HIGH, transparent); } private void doActionAddWatermark() throws PageException, IOException, DocumentException { required("pdf", "addWatermark", "source", source); if (copyFrom == null && image == null) throw new ApplicationException( "at least one of the following attributes must be defined " + "[copyFrom,image]"); if (destination != null && destination.exists() && !overwrite) throw new ApplicationException("destination file [" + destination + "] already exists"); // image Image img = null; if (image != null) { lucee.runtime.img.Image ri = lucee.runtime.img.Image.createImage(pageContext, image, false, false, true, null); img = Image.getInstance(ri.getBufferedImage(), null, false); } // copy From else { byte[] barr; try { Resource res = Caster.toResource(pageContext, copyFrom, true); barr = IOUtil.toBytes(res); } catch (ExpressionException ee) { barr = Caster.toBinary(copyFrom); } img = Image.getInstance(PDFUtil.toImage(barr, 1).getBufferedImage(), null, false); } // position float x = UNDEFINED, y = UNDEFINED; if (!StringUtil.isEmpty(position)) { int index = position.indexOf(','); if (index == -1) throw new ApplicationException("attribute [position] has an invalid value [" + position + "]," + "value should follow one of the following pattern [40,50], [40,] or [,50]"); String strX = position.substring(0, index).trim(); String strY = position.substring(index + 1).trim(); if (!StringUtil.isEmpty(strX)) x = Caster.toIntValue(strX); if (!StringUtil.isEmpty(strY)) y = Caster.toIntValue(strY); } PDFDocument doc = toPDFDocument(source, password, null); doc.setPages(pages); PdfReader reader = doc.getPdfReader(); reader.consolidateNamedDestinations(); boolean destIsSource = destination != null && doc.getResource() != null && destination.equals(doc.getResource()); java.util.List bookmarks = SimpleBookmark.getBookmark(reader); ArrayList master = new ArrayList(); if (bookmarks != null) master.addAll(bookmarks); // output OutputStream os = null; if (!StringUtil.isEmpty(name) || destIsSource) { os = new ByteArrayOutputStream(); } else if (destination != null) { os = destination.getOutputStream(); } try { int len = reader.getNumberOfPages(); PdfStamper stamp = new PdfStamper(reader, os); if (len > 0) { if (x == UNDEFINED || y == UNDEFINED) { PdfImportedPage first = stamp.getImportedPage(reader, 1); if (y == UNDEFINED) y = (first.getHeight() - img.getHeight()) / 2; if (x == UNDEFINED) x = (first.getWidth() - img.getWidth()) / 2; } img.setAbsolutePosition(x, y); //img.setAlignment(Image.ALIGN_JUSTIFIED); ration geht nicht anhand mitte } // rotation if (rotation != 0) { img.setRotationDegrees(rotation); } Set _pages = doc.getPages(); for (int i = 1; i <= len; i++) { if (_pages != null && !_pages.contains(Integer.valueOf(i))) continue; PdfContentByte cb = foreground ? stamp.getOverContent(i) : stamp.getUnderContent(i); PdfGState gs1 = new PdfGState(); //print.out("op:"+opacity); gs1.setFillOpacity(opacity); //gs1.setStrokeOpacity(opacity); cb.setGState(gs1); cb.addImage(img); } if (bookmarks != null) stamp.setOutlines(master); stamp.close(); } finally { IOUtil.closeEL(os); if (os instanceof ByteArrayOutputStream) { if (destination != null) IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray()), destination, true);// MUST overwrite if (!StringUtil.isEmpty(name)) { pageContext.setVariable(name, new PDFDocument(((ByteArrayOutputStream) os).toByteArray(), password)); } } } } private void doActionRemoveWatermark() throws PageException, IOException, DocumentException { required("pdf", "removeWatermark", "source", source); if (destination != null && destination.exists() && !overwrite) throw new ApplicationException("destination file [" + destination + "] already exists"); lucee.runtime.img.Image ri = new lucee.runtime.img.Image(1, 1, BufferedImage.TYPE_INT_RGB, Color.BLACK); Image img = Image.getInstance(ri.getBufferedImage(), null, false); img.setAbsolutePosition(1, 1); PDFDocument doc = toPDFDocument(source, password, null); doc.setPages(pages); PdfReader reader = doc.getPdfReader(); boolean destIsSource = destination != null && doc.getResource() != null && destination.equals(doc.getResource()); java.util.List bookmarks = SimpleBookmark.getBookmark(reader); ArrayList master = new ArrayList(); if (bookmarks != null) master.addAll(bookmarks); // output OutputStream os = null; if (!StringUtil.isEmpty(name) || destIsSource) { os = new ByteArrayOutputStream(); } else if (destination != null) { os = destination.getOutputStream(); } try { int len = reader.getNumberOfPages(); PdfStamper stamp = new PdfStamper(reader, os); Set _pages = doc.getPages(); for (int i = 1; i <= len; i++) { if (_pages != null && !_pages.contains(Integer.valueOf(i))) continue; PdfContentByte cb = foreground ? stamp.getOverContent(i) : stamp.getUnderContent(i); PdfGState gs1 = new PdfGState(); gs1.setFillOpacity(0); cb.setGState(gs1); cb.addImage(img); } if (bookmarks != null) stamp.setOutlines(master); stamp.close(); } finally { IOUtil.closeEL(os); if (os instanceof ByteArrayOutputStream) { if (destination != null) IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray()), destination, true);// MUST overwrite if (!StringUtil.isEmpty(name)) { pageContext.setVariable(name, new PDFDocument(((ByteArrayOutputStream) os).toByteArray(), password)); } } } } private void doActionDeletePages() throws PageException, IOException, DocumentException { required("pdf", "deletePage", "pages", pages, true); required("pdf", "deletePage", "source", source); PDFDocument doc = toPDFDocument(source, password, null); doc.setPages(pages); if (destination == null && StringUtil.isEmpty(name)) { if (doc.getResource() == null) throw new ApplicationException( "source is not based on a resource, destination attribute is required"); destination = doc.getResource(); } else if (destination != null && destination.exists() && !overwrite) throw new ApplicationException("destination file [" + destination + "] already exists"); boolean destIsSource = destination != null && doc.getResource() != null && destination.equals(doc.getResource()); // output OutputStream os = null; if (!StringUtil.isEmpty(name) || destIsSource) { os = new ByteArrayOutputStream(); } else if (destination != null) { os = destination.getOutputStream(); } try { PDFUtil.concat(new PDFDocument[] { doc }, os, true, true, true, version); } finally { //if(document!=null)document.close(); IOUtil.closeEL(os); if (os instanceof ByteArrayOutputStream) { if (destination != null) IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray()), destination, true);// MUST overwrite if (!StringUtil.isEmpty(name)) { pageContext.setVariable(name, new PDFDocument(((ByteArrayOutputStream) os).toByteArray(), password)); } } } } private void doActionMerge() throws ApplicationException, PageException, IOException, DocumentException { if (source == null && params == null && directory == null) throw new ApplicationException("at least one of the following constellation must be defined" + " attribute source, attribute directory or cfpdfparam child tags"); if (destination == null && StringUtil.isEmpty(name, true)) throw new ApplicationException( "at least one of the following attributes must be defined " + "[destination,name]"); if (destination != null && !overwrite) throw new ApplicationException("destination file [" + destination + "] already exists"); ArrayList docs = new ArrayList(); PDFDocument doc; boolean isListing = false; // source if (source != null) { if (Decision.isArray(source)) { Array arr = Caster.toArray(source); int len = arr.size(); for (int i = 1; i <= len; i++) { docs.add(doc = toPDFDocument(arr.getE(i), password, null)); doc.setPages(pages); } } else if (source instanceof String) { String[] sources = ListUtil .toStringArrayTrim(ListUtil.listToArrayRemoveEmpty((String) source, ',')); for (int i = 0; i < sources.length; i++) { docs.add(doc = toPDFDocument(sources[i], password, null)); doc.setPages(pages); } } else docs.add(toPDFDocument(source, password, null)); } boolean destIsSource = false; // params if (directory != null && !directory.isDirectory()) { if (!directory.exists()) throw new ApplicationException("defined attribute directory does not exist"); throw new ApplicationException("defined attribute directory is not a directory"); } if (params != null) { Iterator it = params.iterator(); PDFParamBean param; while (it.hasNext()) { param = (PDFParamBean) it.next(); docs.add(doc = toPDFDocument(param.getSource(), param.getPassword(), directory)); doc.setPages(param.getPages()); } } else if (directory != null) { isListing = true; Resource[] children = ResourceUtil.listResources(directory, filter); if (ascending) { for (int i = children.length - 1; i >= 0; i--) { if (destination != null && children[i].equals(destination)) destIsSource = true; docs.add(doc = toPDFDocument(children[i], password, null)); doc.setPages(pages); } } else { for (int i = 0; i < children.length; i++) { if (destination != null && children[i].equals(destination)) destIsSource = true; docs.add(doc = toPDFDocument(children[i], password, null)); doc.setPages(pages); } } } int doclen = docs.size(); if (doclen == 0) throw new ApplicationException("you have to define at leat 1 pdf file"); // output OutputStream os = null; if (!StringUtil.isEmpty(name) || destIsSource) { os = new ByteArrayOutputStream(); } else if (destination != null) { os = destination.getOutputStream(); } /*com.lowagie.text.Document document=null; PdfCopy copy=null; PdfReader pr; Set pages; int size;*/ try { if (!isListing) stopOnError = true; PDFUtil.concat((PDFDocument[]) docs.toArray(new PDFDocument[docs.size()]), os, keepBookmark, false, stopOnError, version); /* boolean init=false; for(int d=0;d<doclen;d++) { doc=(PDFDocument) docs.get(d); pages=doc.getPages(); try { pr=doc.getPdfReader(); print.out(pr.getCatalog().getKeys()); } catch(Throwable t) { if(isListing && !stopOnError)continue; throw Caster.toPageException(t); } print.out("d+"+d); if(!init) { init=true; print.out("set"); document = new com.lowagie.text.Document(pr.getPageSizeWithRotation(1)); copy = new PdfCopy(document,os); document.open(); } size=pr.getNumberOfPages(); print.out("pages:"+size); for(int page=1;page<=size;page++) { if(pages==null || pages.contains(Constants.Integer(page))) { copy.addPage(copy.getImportedPage(pr, page)); } } }*/ } finally { //if(document!=null)document.close(); IOUtil.closeEL(os); if (os instanceof ByteArrayOutputStream) { if (destination != null) IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray()), destination, true);// MUST overwrite if (!StringUtil.isEmpty(name)) pageContext.setVariable(name, ((ByteArrayOutputStream) os).toByteArray()); } } } private void doActionRead() throws PageException { required("pdf", "read", "name", name, true); required("pdf", "read", "source", source); pageContext.setVariable(name, toPDFDocument(source, password, null)); } private void doActionProtect() throws PageException, IOException, DocumentException { required("pdf", "protect", "source", source); if (StringUtil.isEmpty(newUserPassword) && StringUtil.isEmpty(newOwnerPassword)) throw new ApplicationException( "at least one of the following attributes must be defined [newUserPassword,newOwnerPassword]"); PDFDocument doc = toPDFDocument(source, password, null); if (destination == null) { destination = doc.getResource(); if (destination == null) throw new ApplicationException("source is not based on a resource, destination file is required"); } else if (destination.exists() && !overwrite) throw new ApplicationException("destination file [" + destination + "] already exists"); boolean destIsSource = doc.getResource() != null && destination.equals(doc.getResource()); // output OutputStream os = null; if (destIsSource) { os = new ByteArrayOutputStream(); } else { os = destination.getOutputStream(); } try { PDFUtil.encrypt(doc, os, newUserPassword, newOwnerPassword, permissions, encrypt); } finally { IOUtil.closeEL(os); if (os instanceof ByteArrayOutputStream) { IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray()), destination, true);// MUST overwrite } } } private void doActionSetInfo() throws PageException, IOException, DocumentException { required("pdf", "setInfo", "info", info); required("pdf", "getInfo", "source", source); PDFDocument doc = toPDFDocument(source, password, null); PdfReader pr = doc.getPdfReader(); OutputStream os = null; try { if (destination == null) { if (doc.getResource() == null) throw new ApplicationException( "source is not based on a resource, destination file is required"); destination = doc.getResource(); } else if (destination.exists() && !overwrite) throw new ApplicationException("destination file [" + destination + "] already exists"); PdfStamper stamp = new PdfStamper(pr, os = destination.getOutputStream()); HashMap moreInfo = new HashMap(); //Key[] keys = info.keys(); Iterator<Entry<Key, Object>> it = info.entryIterator(); Entry<Key, Object> e; while (it.hasNext()) { e = it.next(); moreInfo.put(StringUtil.ucFirst(e.getKey().getLowerString()), Caster.toString(e.getValue())); } // author Object value = info.get(KeyConstants._author, null); if (value != null) moreInfo.put("Author", Caster.toString(value)); // keywords value = info.get("keywords", null); if (value != null) moreInfo.put("Keywords", Caster.toString(value)); // title value = info.get(KeyConstants._title, null); if (value != null) moreInfo.put("Title", Caster.toString(value)); // subject value = info.get(KeyConstants._subject, null); if (value != null) moreInfo.put("Subject", Caster.toString(value)); // creator value = info.get("creator", null); if (value != null) moreInfo.put("Creator", Caster.toString(value)); // trapped value = info.get("Trapped", null); if (value != null) moreInfo.put("Trapped", Caster.toString(value)); // Created value = info.get("Created", null); if (value != null) moreInfo.put("Created", Caster.toString(value)); // Language value = info.get("Language", null); if (value != null) moreInfo.put("Language", Caster.toString(value)); stamp.setMoreInfo(moreInfo); stamp.close(); } finally { IOUtil.closeEL(os); pr.close(); } } private void doActionGetInfo() throws PageException { required("pdf", "getInfo", "name", name, true); required("pdf", "getInfo", "source", source); PDFDocument doc = toPDFDocument(source, password, null); pageContext.setVariable(name, doc.getInfo()); } private void doActionExtractText() throws PageException, IOException, CryptographyException, InvalidPasswordException { required("pdf", "extractText", "name", name, true); PDFDocument doc = toPDFDocument(source, password, null); doc.setPages(pages); pageContext.setVariable(name, PDFUtil.extractText(doc, doc.getPages())); /* <cfpdf required action="extracttext" <!---extract all the words in the PDF.---> ***source= "absolute or relative path of the PDF file|PDF document variable| cfdocument variable" pages = "*" <!----page numbers from where the text needs to be extracted from the PDF document---> optional addquads = "add the position or quadrants for the text in the PDF" honourspaces = "true|false" overwrite = "true" <!---Overwrite the specified object in the PDF document---> ***password = "" <!--- PDF document password---> type = "string|xml" <!---format in which the text needs to be extracted---> one of the following: destination = "PDF output file pathname" name = "PDF document variable" usestructure = "true|false" * */ } private Object allowed(boolean encrypted, int permissions, int permission) { return (!encrypted || (permissions & permission) > 0) ? "Allowed" : "Not Allowed"; } private PDFDocument toPDFDocument(Object source, String password, Resource directory) throws PageException { if (source instanceof PDFDocument) return (PDFDocument) source; if (Decision.isBinary(source)) { return new PDFDocument(Caster.toBinary(source), password); } if (source instanceof Resource) { return new PDFDocument((Resource) source, password); } if (source instanceof String) { if (directory != null) { Resource res = directory.getRealResource((String) source); if (!res.isFile()) { Resource res2 = ResourceUtil.toResourceNotExisting(pageContext, (String) source); if (res2.isFile()) res = res2; else throw new ExpressionException("file or directory " + res + " not exist"); } return new PDFDocument(res, password); } return new PDFDocument(ResourceUtil.toResourceExisting(pageContext, (String) source), password); } throw new CasterException(source, PdfReader.class); } /*private byte[] toBinary(Object source) throws ExpressionException, IOException { if(source instanceof PDFDocument) return toBinary(((PDFDocument)source).getResource()); if(Decision.isBinary(source)){ return Caster.toBinary(source); } if(source instanceof Resource){ return IOUtil.toBytes((Resource)source); } if(source instanceof String){ if(directory!=null) { Resource res = directory.getRealResource((String)source); if(!res.isFile()){ Resource res2 = ResourceUtil.toResourceNotExisting(pageContext, (String)source); if(res2.isFile()) res=res2; else throw new ExpressionException("file or directory "+res+" not exist"); } return IOUtil.toBytes(res); } return IOUtil.toBytes(ResourceUtil.toResourceExisting(pageContext, (String)source)); } throw new CasterException(source,PdfReader.class); }*/ protected void setParam(PDFParamBean param) { if (params == null) params = new ArrayList<PDFParamBean>(); params.add(param); } }