Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]
    1   /*
    2    * Copyright 2003, 2004 by Paulo Soares.
    3    *
    4    * The contents of this file are subject to the Mozilla Public License Version 1.1
    5    * (the "License"); you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
    7    *
    8    * Software distributed under the License is distributed on an "AS IS" basis,
    9    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   10    * for the specific language governing rights and limitations under the License.
   11    *
   12    * The Original Code is 'iText, a free JAVA-PDF library'.
   13    *
   14    * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
   15    * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
   16    * All Rights Reserved.
   17    * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
   18    * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
   19    *
   20    * Contributor(s): all the names of the contributors are added in the source code
   21    * where applicable.
   22    *
   23    * Alternatively, the contents of this file may be used under the terms of the
   24    * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
   25    * provisions of LGPL are applicable instead of those above.  If you wish to
   26    * allow use of your version of this file only under the terms of the LGPL
   27    * License and not to allow others to use your version of this file under
   28    * the MPL, indicate your decision by deleting the provisions above and
   29    * replace them with the notice and other provisions required by the LGPL.
   30    * If you do not delete the provisions above, a recipient may use your version
   31    * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
   32    *
   33    * This library is free software; you can redistribute it and/or modify it
   34    * under the terms of the MPL as stated above or under the terms of the GNU
   35    * Library General Public License as published by the Free Software Foundation;
   36    * either version 2 of the License, or any later version.
   37    *
   38    * This library is distributed in the hope that it will be useful, but WITHOUT
   39    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   40    * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
   41    * details.
   42    *
   43    * If you didn't download this code from the following link, you should check if
   44    * you aren't using an obsolete version:
   45    * http://www.lowagie.com/iText/
   46    */
   47   package com.lowagie.text.pdf;
   48   
   49   import java.io.File;
   50   import java.io.FileOutputStream;
   51   import java.io.IOException;
   52   import java.io.InputStream;
   53   import java.io.OutputStream;
   54   import java.security.SignatureException;
   55   import java.util.HashMap;
   56   import java.util.List;
   57   import java.util.Map;
   58   
   59   import com.lowagie.text.DocWriter;
   60   import com.lowagie.text.DocumentException;
   61   import com.lowagie.text.ExceptionConverter;
   62   import com.lowagie.text.Image;
   63   import com.lowagie.text.Rectangle;
   64   import com.lowagie.text.pdf.collection.PdfCollection;
   65   import com.lowagie.text.pdf.interfaces.PdfEncryptionSettings;
   66   import com.lowagie.text.pdf.interfaces.PdfViewerPreferences;
   67   import java.security.cert.Certificate;
   68   
   69   /** Applies extra content to the pages of a PDF document.
   70    * This extra content can be all the objects allowed in PdfContentByte
   71    * including pages from other Pdfs. The original PDF will keep
   72    * all the interactive elements including bookmarks, links and form fields.
   73    * <p>
   74    * It is also possible to change the field values and to
   75    * flatten them. New fields can be added but not flattened.
   76    * @author Paulo Soares (psoares@consiste.pt)
   77    */
   78   public class PdfStamper
   79   	implements PdfViewerPreferences, PdfEncryptionSettings {
   80       /**
   81        * The writer
   82        */    
   83       protected PdfStamperImp stamper;
   84       private HashMap moreInfo;
   85       private boolean hasSignature;
   86       private PdfSignatureAppearance sigApp;
   87   
   88       /** Starts the process of adding extra content to an existing PDF
   89        * document.
   90        * @param reader the original document. It cannot be reused
   91        * @param os the output stream
   92        * @throws DocumentException on error
   93        * @throws IOException on error
   94        */
   95       public PdfStamper(PdfReader reader, OutputStream os) throws DocumentException, IOException {
   96           stamper = new PdfStamperImp(reader, os, '\0', false);
   97       }
   98   
   99       /**
  100        * Starts the process of adding extra content to an existing PDF
  101        * document.
  102        * @param reader the original document. It cannot be reused
  103        * @param os the output stream
  104        * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
  105        * document
  106        * @throws DocumentException on error
  107        * @throws IOException on error
  108        */
  109       public PdfStamper(PdfReader reader, OutputStream os, char pdfVersion) throws DocumentException, IOException {
  110           stamper = new PdfStamperImp(reader, os, pdfVersion, false);
  111       }
  112   
  113       /**
  114        * Starts the process of adding extra content to an existing PDF
  115        * document, possibly as a new revision.
  116        * @param reader the original document. It cannot be reused
  117        * @param os the output stream
  118        * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
  119        * document
  120        * @param append if <CODE>true</CODE> appends the document changes as a new revision. This is
  121        * only useful for multiple signatures as nothing is gained in speed or memory
  122        * @throws DocumentException on error
  123        * @throws IOException on error
  124        */
  125       public PdfStamper(PdfReader reader, OutputStream os, char pdfVersion, boolean append) throws DocumentException, IOException {
  126           stamper = new PdfStamperImp(reader, os, pdfVersion, append);
  127       }
  128   
  129       /** Gets the optional <CODE>String</CODE> map to add or change values in
  130        * the info dictionary.
  131        * @return the map or <CODE>null</CODE>
  132        *
  133        */
  134       public HashMap getMoreInfo() {
  135           return this.moreInfo;
  136       }
  137   
  138       /** An optional <CODE>String</CODE> map to add or change values in
  139        * the info dictionary. Entries with <CODE>null</CODE>
  140        * values delete the key in the original info dictionary
  141        * @param moreInfo additional entries to the info dictionary
  142        *
  143        */
  144       public void setMoreInfo(HashMap moreInfo) {
  145           this.moreInfo = moreInfo;
  146       }
  147   
  148       /**
  149        * Replaces a page from this document with a page from other document. Only the content
  150        * is replaced not the fields and annotations. This method must be called before 
  151        * getOverContent() or getUndercontent() are called for the same page.
  152        * @param r the <CODE>PdfReader</CODE> from where the new page will be imported
  153        * @param pageImported the page number of the imported page
  154        * @param pageReplaced the page to replace in this document
  155        * @since iText 2.1.1
  156        */
  157       public void replacePage(PdfReader r, int pageImported, int pageReplaced) {
  158           stamper.replacePage(r, pageImported, pageReplaced);
  159       }
  160       
  161       /**
  162        * Inserts a blank page. All the pages above and including <CODE>pageNumber</CODE> will
  163        * be shifted up. If <CODE>pageNumber</CODE> is bigger than the total number of pages
  164        * the new page will be the last one.
  165        * @param pageNumber the page number position where the new page will be inserted
  166        * @param mediabox the size of the new page
  167        */    
  168       public void insertPage(int pageNumber, Rectangle mediabox) {
  169           stamper.insertPage(pageNumber, mediabox);
  170       }
  171       
  172       /**
  173        * Gets the signing instance. The appearances and other parameters can the be set.
  174        * @return the signing instance
  175        */    
  176       public PdfSignatureAppearance getSignatureAppearance() {
  177           return sigApp;
  178       }
  179   
  180       /**
  181        * Closes the document. No more content can be written after the
  182        * document is closed.
  183        * <p>
  184        * If closing a signed document with an external signature the closing must be done
  185        * in the <CODE>PdfSignatureAppearance</CODE> instance.
  186        * @throws DocumentException on error
  187        * @throws IOException on error
  188        */
  189       public void close() throws DocumentException, IOException {
  190           if (!hasSignature) {
  191               stamper.close(moreInfo);
  192               return;
  193           }
  194           sigApp.preClose();
  195           PdfSigGenericPKCS sig = sigApp.getSigStandard();
  196           PdfLiteral lit = (PdfLiteral)sig.get(PdfName.CONTENTS);
  197           int totalBuf = (lit.getPosLength() - 2) / 2;
  198           byte buf[] = new byte[8192];
  199           int n;
  200           InputStream inp = sigApp.getRangeStream();
  201           try {
  202               while ((n = inp.read(buf)) > 0) {
  203                   sig.getSigner().update(buf, 0, n);
  204               }
  205           }
  206           catch (SignatureException se) {
  207               throw new ExceptionConverter(se);
  208           }
  209           buf = new byte[totalBuf];
  210           byte[] bsig = sig.getSignerContents();
  211           System.arraycopy(bsig, 0, buf, 0, bsig.length);
  212           PdfString str = new PdfString(buf);
  213           str.setHexWriting(true);
  214           PdfDictionary dic = new PdfDictionary();
  215           dic.put(PdfName.CONTENTS, str);
  216           sigApp.close(dic);
  217           stamper.reader.close();
  218       }
  219   
  220       /** Gets a <CODE>PdfContentByte</CODE> to write under the page of
  221        * the original document.
  222        * @param pageNum the page number where the extra content is written
  223        * @return a <CODE>PdfContentByte</CODE> to write under the page of
  224        * the original document
  225        */
  226       public PdfContentByte getUnderContent(int pageNum) {
  227           return stamper.getUnderContent(pageNum);
  228       }
  229   
  230       /** Gets a <CODE>PdfContentByte</CODE> to write over the page of
  231        * the original document.
  232        * @param pageNum the page number where the extra content is written
  233        * @return a <CODE>PdfContentByte</CODE> to write over the page of
  234        * the original document
  235        */
  236       public PdfContentByte getOverContent(int pageNum) {
  237           return stamper.getOverContent(pageNum);
  238       }
  239   
  240       /** Checks if the content is automatically adjusted to compensate
  241        * the original page rotation.
  242        * @return the auto-rotation status
  243        */
  244       public boolean isRotateContents() {
  245           return stamper.isRotateContents();
  246       }
  247   
  248       /** Flags the content to be automatically adjusted to compensate
  249        * the original page rotation. The default is <CODE>true</CODE>.
  250        * @param rotateContents <CODE>true</CODE> to set auto-rotation, <CODE>false</CODE>
  251        * otherwise
  252        */
  253       public void setRotateContents(boolean rotateContents) {
  254           stamper.setRotateContents(rotateContents);
  255       }
  256   
  257       /** Sets the encryption options for this document. The userPassword and the
  258        *  ownerPassword can be null or have zero length. In this case the ownerPassword
  259        *  is replaced by a random string. The open permissions for the document can be
  260        *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
  261        *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
  262        *  The permissions can be combined by ORing them.
  263        * @param userPassword the user password. Can be null or empty
  264        * @param ownerPassword the owner password. Can be null or empty
  265        * @param permissions the user permissions
  266        * @param strength128Bits <code>true</code> for 128 bit key length, <code>false</code> for 40 bit key length
  267        * @throws DocumentException if anything was already written to the output
  268        */
  269       public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits) throws DocumentException {
  270           if (stamper.isAppend())
  271               throw new DocumentException("Append mode does not support changing the encryption status.");
  272           if (stamper.isContentWritten())
  273               throw new DocumentException("Content was already written to the output.");
  274           stamper.setEncryption(userPassword, ownerPassword, permissions, strength128Bits ? PdfWriter.STANDARD_ENCRYPTION_128 : PdfWriter.STANDARD_ENCRYPTION_40);
  275       }
  276   
  277       /** Sets the encryption options for this document. The userPassword and the
  278        *  ownerPassword can be null or have zero length. In this case the ownerPassword
  279        *  is replaced by a random string. The open permissions for the document can be
  280        *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
  281        *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
  282        *  The permissions can be combined by ORing them.
  283        * @param userPassword the user password. Can be null or empty
  284        * @param ownerPassword the owner password. Can be null or empty
  285        * @param permissions the user permissions
  286        * @param encryptionType the type of encryption. It can be one of STANDARD_ENCRYPTION_40, STANDARD_ENCRYPTION_128 or ENCRYPTION_AES128.
  287        * Optionally DO_NOT_ENCRYPT_METADATA can be ored to output the metadata in cleartext
  288        * @throws DocumentException if the document is already open
  289        */
  290       public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, int encryptionType) throws DocumentException {
  291           if (stamper.isAppend())
  292               throw new DocumentException("Append mode does not support changing the encryption status.");
  293           if (stamper.isContentWritten())
  294               throw new DocumentException("Content was already written to the output.");
  295           stamper.setEncryption(userPassword, ownerPassword, permissions, encryptionType);
  296       }
  297   
  298       /**
  299        * Sets the encryption options for this document. The userPassword and the
  300        *  ownerPassword can be null or have zero length. In this case the ownerPassword
  301        *  is replaced by a random string. The open permissions for the document can be
  302        *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
  303        *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
  304        *  The permissions can be combined by ORing them.
  305        * @param strength <code>true</code> for 128 bit key length, <code>false</code> for 40 bit key length
  306        * @param userPassword the user password. Can be null or empty
  307        * @param ownerPassword the owner password. Can be null or empty
  308        * @param permissions the user permissions
  309        * @throws DocumentException if anything was already written to the output
  310        */
  311       public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions) throws DocumentException {
  312           setEncryption(DocWriter.getISOBytes(userPassword), DocWriter.getISOBytes(ownerPassword), permissions, strength);
  313       }
  314   
  315       /**
  316        * Sets the encryption options for this document. The userPassword and the
  317        *  ownerPassword can be null or have zero length. In this case the ownerPassword
  318        *  is replaced by a random string. The open permissions for the document can be
  319        *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
  320        *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
  321        *  The permissions can be combined by ORing them.
  322        * @param encryptionType the type of encryption. It can be one of STANDARD_ENCRYPTION_40, STANDARD_ENCRYPTION_128 or ENCRYPTION_AES128.
  323        * Optionally DO_NOT_ENCRYPT_METADATA can be ored to output the metadata in cleartext
  324        * @param userPassword the user password. Can be null or empty
  325        * @param ownerPassword the owner password. Can be null or empty
  326        * @param permissions the user permissions
  327        * @throws DocumentException if anything was already written to the output
  328        */
  329       public void setEncryption(int encryptionType, String userPassword, String ownerPassword, int permissions) throws DocumentException {
  330           setEncryption(DocWriter.getISOBytes(userPassword), DocWriter.getISOBytes(ownerPassword), permissions, encryptionType);
  331       }
  332   
  333       /**
  334        * Sets the certificate encryption options for this document. An array of one or more public certificates
  335        * must be provided together with an array of the same size for the permissions for each certificate.
  336        *  The open permissions for the document can be
  337        *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
  338        *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
  339        *  The permissions can be combined by ORing them.
  340        * Optionally DO_NOT_ENCRYPT_METADATA can be ored to output the metadata in cleartext
  341        * @param certs the public certificates to be used for the encryption
  342        * @param permissions the user permissions for each of the certificates
  343        * @param encryptionType the type of encryption. It can be one of STANDARD_ENCRYPTION_40, STANDARD_ENCRYPTION_128 or ENCRYPTION_AES128.
  344        * @throws DocumentException if the encryption was set too late
  345        */
  346        public void setEncryption(Certificate[] certs, int[] permissions, int encryptionType) throws DocumentException {
  347           if (stamper.isAppend())
  348               throw new DocumentException("Append mode does not support changing the encryption status.");
  349           if (stamper.isContentWritten())
  350               throw new DocumentException("Content was already written to the output.");
  351           stamper.setEncryption(certs, permissions, encryptionType);
  352        }
  353        
  354       /** Gets a page from other PDF document. Note that calling this method more than
  355        * once with the same parameters will retrieve the same object.
  356        * @param reader the PDF document where the page is
  357        * @param pageNumber the page number. The first page is 1
  358        * @return the template representing the imported page
  359        */
  360       public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
  361           return stamper.getImportedPage(reader, pageNumber);
  362       }
  363   
  364       /** Gets the underlying PdfWriter.
  365        * @return the underlying PdfWriter
  366        */
  367       public PdfWriter getWriter() {
  368           return stamper;
  369       }
  370   
  371       /** Gets the underlying PdfReader.
  372        * @return the underlying PdfReader
  373        */
  374       public PdfReader getReader() {
  375           return stamper.reader;
  376       }
  377   
  378       /** Gets the <CODE>AcroFields</CODE> object that allows to get and set field values
  379        * and to merge FDF forms.
  380        * @return the <CODE>AcroFields</CODE> object
  381        */
  382       public AcroFields getAcroFields() {
  383           return stamper.getAcroFields();
  384       }
  385   
  386       /** Determines if the fields are flattened on close. The fields added with
  387        * {@link #addAnnotation(PdfAnnotation,int)} will never be flattened.
  388        * @param flat <CODE>true</CODE> to flatten the fields, <CODE>false</CODE>
  389        * to keep the fields
  390        */
  391       public void setFormFlattening(boolean flat) {
  392           stamper.setFormFlattening(flat);
  393       }
  394   
  395       /** Determines if the FreeText annotations are flattened on close. 
  396        * @param flat <CODE>true</CODE> to flatten the FreeText annotations, <CODE>false</CODE>
  397        * (the default) to keep the FreeText annotations as active content.
  398        */
  399       public void setFreeTextFlattening(boolean flat) {
  400       	stamper.setFreeTextFlattening(flat);
  401   	}
  402   
  403       /**
  404        * Adds an annotation of form field in a specific page. This page number
  405        * can be overridden with {@link PdfAnnotation#setPlaceInPage(int)}.
  406        * @param annot the annotation
  407        * @param page the page
  408        */
  409       public void addAnnotation(PdfAnnotation annot, int page) {
  410           stamper.addAnnotation(annot, page);
  411       }
  412   
  413       /**
  414        * Adds the comments present in an FDF file.
  415        * @param fdf the FDF file
  416        * @throws IOException on error
  417        */    
  418       public void addComments(FdfReader fdf) throws IOException {
  419           stamper.addComments(fdf);
  420       }
  421       
  422       /**
  423        * Sets the bookmarks. The list structure is defined in
  424        * {@link SimpleBookmark}.
  425        * @param outlines the bookmarks or <CODE>null</CODE> to remove any
  426        */
  427       public void setOutlines(List outlines) {
  428           stamper.setOutlines(outlines);
  429       }
  430   
  431       /**
  432        * Sets the thumbnail image for a page.
  433        * @param image the image
  434        * @param page the page
  435        * @throws PdfException on error
  436        * @throws DocumentException on error
  437        */    
  438       public void setThumbnail(Image image, int page) throws PdfException, DocumentException {
  439           stamper.setThumbnail(image, page);
  440       }
  441       
  442       /**
  443        * Adds <CODE>name</CODE> to the list of fields that will be flattened on close,
  444        * all the other fields will remain. If this method is never called or is called
  445        * with invalid field names, all the fields will be flattened.
  446        * <p>
  447        * Calling <CODE>setFormFlattening(true)</CODE> is needed to have any kind of
  448        * flattening.
  449        * @param name the field name
  450        * @return <CODE>true</CODE> if the field exists, <CODE>false</CODE> otherwise
  451        */
  452       public boolean partialFormFlattening(String name) {
  453           return stamper.partialFormFlattening(name);
  454       }
  455   
  456       /** Adds a JavaScript action at the document level. When the document
  457        * opens all this JavaScript runs. The existing JavaScript will be replaced.
  458        * @param js the JavaScript code
  459        */
  460       public void addJavaScript(String js) {
  461           stamper.addJavaScript(js, !PdfEncodings.isPdfDocEncoding(js));
  462       }
  463   
  464       /** Adds a file attachment at the document level. Existing attachments will be kept.
  465        * @param description the file description
  466        * @param fileStore an array with the file. If it's <CODE>null</CODE>
  467        * the file will be read from the disk
  468        * @param file the path to the file. It will only be used if
  469        * <CODE>fileStore</CODE> is not <CODE>null</CODE>
  470        * @param fileDisplay the actual file name stored in the pdf
  471        * @throws IOException on error
  472        */    
  473       public void addFileAttachment(String description, byte fileStore[], String file, String fileDisplay) throws IOException {
  474           addFileAttachment(description, PdfFileSpecification.fileEmbedded(stamper, file, fileDisplay, fileStore));
  475       }
  476   
  477       /** Adds a file attachment at the document level. Existing attachments will be kept.
  478        * @param description the file description
  479        * @param fs the file specification
  480        */    
  481       public void addFileAttachment(String description, PdfFileSpecification fs) throws IOException {
  482           stamper.addFileAttachment(description, fs);
  483       }
  484   
  485       /**
  486        * This is the most simple way to change a PDF into a
  487        * portable collection. Choose one of the following names:
  488        * <ul>
  489        * <li>PdfName.D (detailed view)
  490        * <li>PdfName.T (tiled view)
  491        * <li>PdfName.H (hidden)
  492        * </ul>
  493        * Pass this name as a parameter and your PDF will be
  494        * a portable collection with all the embedded and
  495        * attached files as entries.
  496        * @param initialView can be PdfName.D, PdfName.T or PdfName.H
  497        */
  498       public void makePackage( PdfName initialView ) {
  499       	PdfCollection collection = new PdfCollection(0);
  500       	collection.put(PdfName.VIEW, initialView);
  501       	stamper.makePackage( collection );
  502       }
  503   
  504       /**
  505        * Adds or replaces the Collection Dictionary in the Catalog.
  506        * @param	collection	the new collection dictionary.
  507        */
  508       public void makePackage(PdfCollection collection) {
  509       	stamper.makePackage(collection);    	
  510       }
  511       
  512       /**
  513        * Sets the viewer preferences.
  514        * @param preferences the viewer preferences
  515        * @see PdfViewerPreferences#setViewerPreferences(int)
  516        */
  517       public void setViewerPreferences(int preferences) {
  518           stamper.setViewerPreferences(preferences);
  519       }
  520       
  521       /** Adds a viewer preference
  522        * @param key a key for a viewer preference
  523        * @param value the value for the viewer preference
  524        * @see PdfViewerPreferences#addViewerPreference
  525        */
  526       
  527       public void addViewerPreference(PdfName key, PdfObject value) {
  528       	stamper.addViewerPreference(key, value);
  529       }
  530   
  531       /**
  532        * Sets the XMP metadata.
  533        * @param xmp
  534        * @see PdfWriter#setXmpMetadata(byte[])
  535        */
  536       public void setXmpMetadata(byte[] xmp) {
  537           stamper.setXmpMetadata(xmp);
  538       }
  539   
  540       /**
  541        * Gets the 1.5 compression status.
  542        * @return <code>true</code> if the 1.5 compression is on
  543        */
  544       public boolean isFullCompression() {
  545           return stamper.isFullCompression();
  546       }
  547   
  548       /**
  549        * Sets the document's compression to the new 1.5 mode with object streams and xref
  550        * streams. It can be set at any time but once set it can't be unset.
  551        */
  552       public void setFullCompression() {
  553           if (stamper.isAppend())
  554               return;
  555           stamper.setFullCompression();
  556       }
  557   
  558       /**
  559        * Sets the open and close page additional action.
  560        * @param actionType the action type. It can be <CODE>PdfWriter.PAGE_OPEN</CODE>
  561        * or <CODE>PdfWriter.PAGE_CLOSE</CODE>
  562        * @param action the action to perform
  563        * @param page the page where the action will be applied. The first page is 1
  564        * @throws PdfException if the action type is invalid
  565        */    
  566       public void setPageAction(PdfName actionType, PdfAction action, int page) throws PdfException {
  567           stamper.setPageAction(actionType, action, page);
  568       }
  569   
  570       /**
  571        * Sets the display duration for the page (for presentations)
  572        * @param seconds   the number of seconds to display the page. A negative value removes the entry
  573        * @param page the page where the duration will be applied. The first page is 1
  574        */
  575       public void setDuration(int seconds, int page) {
  576           stamper.setDuration(seconds, page);
  577       }
  578       
  579       /**
  580        * Sets the transition for the page
  581        * @param transition   the transition object. A <code>null</code> removes the transition
  582        * @param page the page where the transition will be applied. The first page is 1
  583        */
  584       public void setTransition(PdfTransition transition, int page) {
  585           stamper.setTransition(transition, page);
  586       }
  587   
  588       /**
  589        * Applies a digital signature to a document, possibly as a new revision, making
  590        * possible multiple signatures. The returned PdfStamper
  591        * can be used normally as the signature is only applied when closing.
  592        * <p>
  593        * A possible use for adding a signature without invalidating an existing one is:
  594        * <p>
  595        * <pre>
  596        * KeyStore ks = KeyStore.getInstance("pkcs12");
  597        * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
  598        * String alias = (String)ks.aliases().nextElement();
  599        * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
  600        * Certificate[] chain = ks.getCertificateChain(alias);
  601        * PdfReader reader = new PdfReader("original.pdf");
  602        * FileOutputStream fout = new FileOutputStream("signed.pdf");
  603        * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', new
  604        * File("/temp"), true);
  605        * PdfSignatureAppearance sap = stp.getSignatureAppearance();
  606        * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
  607        * sap.setReason("I'm the author");
  608        * sap.setLocation("Lisbon");
  609        * // comment next line to have an invisible signature
  610        * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
  611        * stp.close();
  612        * </pre>
  613        * @param reader the original document
  614        * @param os the output stream or <CODE>null</CODE> to keep the document in the temporary file
  615        * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
  616        * document
  617        * @param tempFile location of the temporary file. If it's a directory a temporary file will be created there.
  618        *     If it's a file it will be used directly. The file will be deleted on exit unless <CODE>os</CODE> is null.
  619        *     In that case the document can be retrieved directly from the temporary file. If it's <CODE>null</CODE>
  620        *     no temporary file will be created and memory will be used
  621        * @param append if <CODE>true</CODE> the signature and all the other content will be added as a
  622        * new revision thus not invalidating existing signatures
  623        * @return a <CODE>PdfStamper</CODE>
  624        * @throws DocumentException on error
  625        * @throws IOException on error
  626        */
  627       public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion, File tempFile, boolean append) throws DocumentException, IOException {
  628           PdfStamper stp;
  629           if (tempFile == null) {
  630               ByteBuffer bout = new ByteBuffer();
  631               stp = new PdfStamper(reader, bout, pdfVersion, append);
  632               stp.sigApp = new PdfSignatureAppearance(stp.stamper);
  633               stp.sigApp.setSigout(bout);
  634           }
  635           else {
  636               if (tempFile.isDirectory())
  637                   tempFile = File.createTempFile("pdf", null, tempFile);
  638               FileOutputStream fout = new FileOutputStream(tempFile);
  639               stp = new PdfStamper(reader, fout, pdfVersion, append);
  640               stp.sigApp = new PdfSignatureAppearance(stp.stamper);
  641               stp.sigApp.setTempFile(tempFile);
  642           }
  643           stp.sigApp.setOriginalout(os);
  644           stp.sigApp.setStamper(stp);
  645           stp.hasSignature = true;
  646           PdfDictionary catalog = reader.getCatalog();
  647           PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
  648           if (acroForm != null) {
  649               acroForm.remove(PdfName.NEEDAPPEARANCES);
  650               stp.stamper.markUsed(acroForm);
  651           }
  652           return stp;
  653       }
  654   
  655       /**
  656        * Applies a digital signature to a document. The returned PdfStamper
  657        * can be used normally as the signature is only applied when closing.
  658        * <p>
  659        * Note that the pdf is created in memory.
  660        * <p>
  661        * A possible use is:
  662        * <p>
  663        * <pre>
  664        * KeyStore ks = KeyStore.getInstance("pkcs12");
  665        * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
  666        * String alias = (String)ks.aliases().nextElement();
  667        * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
  668        * Certificate[] chain = ks.getCertificateChain(alias);
  669        * PdfReader reader = new PdfReader("original.pdf");
  670        * FileOutputStream fout = new FileOutputStream("signed.pdf");
  671        * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
  672        * PdfSignatureAppearance sap = stp.getSignatureAppearance();
  673        * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
  674        * sap.setReason("I'm the author");
  675        * sap.setLocation("Lisbon");
  676        * // comment next line to have an invisible signature
  677        * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
  678        * stp.close();
  679        * </pre>
  680        * @param reader the original document
  681        * @param os the output stream
  682        * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
  683        * document
  684        * @throws DocumentException on error
  685        * @throws IOException on error
  686        * @return a <CODE>PdfStamper</CODE>
  687        */
  688       public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion) throws DocumentException, IOException {
  689           return createSignature(reader, os, pdfVersion, null, false);
  690       }
  691       
  692       /**
  693        * Applies a digital signature to a document. The returned PdfStamper
  694        * can be used normally as the signature is only applied when closing.
  695        * <p>
  696        * A possible use is:
  697        * <p>
  698        * <pre>
  699        * KeyStore ks = KeyStore.getInstance("pkcs12");
  700        * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
  701        * String alias = (String)ks.aliases().nextElement();
  702        * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
  703        * Certificate[] chain = ks.getCertificateChain(alias);
  704        * PdfReader reader = new PdfReader("original.pdf");
  705        * FileOutputStream fout = new FileOutputStream("signed.pdf");
  706        * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', new File("/temp"));
  707        * PdfSignatureAppearance sap = stp.getSignatureAppearance();
  708        * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
  709        * sap.setReason("I'm the author");
  710        * sap.setLocation("Lisbon");
  711        * // comment next line to have an invisible signature
  712        * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
  713        * stp.close();
  714        * </pre>
  715        * @param reader the original document
  716        * @param os the output stream or <CODE>null</CODE> to keep the document in the temporary file
  717        * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
  718        * document
  719        * @param tempFile location of the temporary file. If it's a directory a temporary file will be created there.
  720        *     If it's a file it will be used directly. The file will be deleted on exit unless <CODE>os</CODE> is null.
  721        *     In that case the document can be retrieved directly from the temporary file. If it's <CODE>null</CODE>
  722        *     no temporary file will be created and memory will be used
  723        * @return a <CODE>PdfStamper</CODE>
  724        * @throws DocumentException on error
  725        * @throws IOException on error
  726        */
  727       public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion, File tempFile) throws DocumentException, IOException 
  728       {
  729           return createSignature(reader, os, pdfVersion, tempFile, false);
  730       }
  731       
  732       /**
  733        * Gets the PdfLayer objects in an existing document as a Map
  734        * with the names/titles of the layers as keys.
  735        * @return	a Map with all the PdfLayers in the document (and the name/title of the layer as key)
  736        * @since	2.1.2
  737        */
  738       public Map getPdfLayers() {
  739       	return stamper.getPdfLayers();
  740       }
  741   }

Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]