📄 pdfsignatureappearance.java
字号:
/*
* $Id: PdfSignatureAppearance.java 2752 2007-05-15 14:58:33Z blowagie $
*
* Copyright 2004-2006 by Paulo Soares.
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the License.
*
* The Original Code is 'iText, a free JAVA-PDF library'.
*
* The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
* the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
* All Rights Reserved.
* Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
* are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
*
* Contributor(s): all the names of the contributors are added in the source code
* where applicable.
*
* Alternatively, the contents of this file may be used under the terms of the
* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
* provisions of LGPL are applicable instead of those above. If you wish to
* allow use of your version of this file only under the terms of the LGPL
* License and not to allow others to use your version of this file under
* the MPL, indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by the LGPL.
* If you do not delete the provisions above, a recipient may use your version
* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MPL as stated above or under the terms of the GNU
* Library General Public License as published by the Free Software Foundation;
* either version 2 of the License, or 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 Library general Public License for more
* details.
*
* If you didn't download this code from the following link, you should check if
* you aren't using an obsolete version:
* http://www.lowagie.com/iText/
*/
package com.lowagie.text.pdf;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.security.PrivateKey;
import java.security.cert.CRL;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.lowagie.text.Chunk;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.ExceptionConverter;
import com.lowagie.text.Font;
import com.lowagie.text.Image;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
/**
* This class takes care of the cryptographic options and appearances that form a signature.
*/
public class PdfSignatureAppearance {
/**
* The rendering mode is just the description
*/
public static final int SignatureRenderDescription = 0;
/**
* The rendering mode is the name of the signer and the description
*/
public static final int SignatureRenderNameAndDescription = 1;
/**
* The rendering mode is an image and the description
*/
public static final int SignatureRenderGraphicAndDescription = 2;
/**
* The self signed filter.
*/
public static final PdfName SELF_SIGNED = PdfName.ADOBE_PPKLITE;
/**
* The VeriSign filter.
*/
public static final PdfName VERISIGN_SIGNED = PdfName.VERISIGN_PPKVS;
/**
* The Windows Certificate Security.
*/
public static final PdfName WINCER_SIGNED = PdfName.ADOBE_PPKMS;
public static final int NOT_CERTIFIED = 0;
public static final int CERTIFIED_NO_CHANGES_ALLOWED = 1;
public static final int CERTIFIED_FORM_FILLING = 2;
public static final int CERTIFIED_FORM_FILLING_AND_ANNOTATIONS = 3;
private static final float TOP_SECTION = 0.3f;
private static final float MARGIN = 2;
private Rectangle rect;
private Rectangle pageRect;
private PdfTemplate app[] = new PdfTemplate[5];
private PdfTemplate frm;
private PdfStamperImp writer;
private String layer2Text;
private String reason;
private String location;
private Calendar signDate;
private String provider;
private int page = 1;
private String fieldName;
private PrivateKey privKey;
private Certificate[] certChain;
private CRL[] crlList;
private PdfName filter;
private boolean newField;
private ByteBuffer sigout;
private OutputStream originalout;
private File tempFile;
private PdfDictionary cryptoDictionary;
private PdfStamper stamper;
private boolean preClosed = false;
private PdfSigGenericPKCS sigStandard;
private int range[];
private RandomAccessFile raf;
private byte bout[];
private int boutLen;
private byte externalDigest[];
private byte externalRSAdata[];
private String digestEncryptionAlgorithm;
private HashMap exclusionLocations;
PdfSignatureAppearance(PdfStamperImp writer) {
this.writer = writer;
signDate = new GregorianCalendar();
fieldName = getNewSigName();
}
private int render = SignatureRenderDescription;
/**
* Gets the rendering mode for this signature.
* @return the rendering mode for this signature
*/
public int getRender() {
return render;
}
/**
* Sets the rendering mode for this signature.
* The rendering modes can be the constants <CODE>SignatureRenderDescription</CODE>,
* <CODE>SignatureRenderNameAndDescription</CODE> or <CODE>SignatureRenderGraphicAndDescription</CODE>.
* The two last modes should be used with Acrobat 6 layer type.
* @param render the render mode
*/
public void setRender(int render) {
this.render = render;
}
private Image signatureGraphic = null;
/**
* Gets the Image object to render.
* @return the image
*/
public Image getSignatureGraphic() {
return signatureGraphic;
}
/**
* Sets the Image object to render when Render is set to <CODE>SignatureRenderGraphicAndDescription</CODE>
* @param signatureGraphic image rendered. If <CODE>null</CODE> the mode is defaulted
* to <CODE>SignatureRenderDescription</CODE>
*/
public void setSignatureGraphic(Image signatureGraphic) {
this.signatureGraphic = signatureGraphic;
}
/**
* Sets the signature text identifying the signer.
* @param text the signature text identifying the signer. If <CODE>null</CODE> or not set
* a standard description will be used
*/
public void setLayer2Text(String text) {
layer2Text = text;
}
/**
* Gets the signature text identifying the signer if set by setLayer2Text().
* @return the signature text identifying the signer
*/
public String getLayer2Text() {
return layer2Text;
}
/**
* Sets the text identifying the signature status.
* @param text the text identifying the signature status. If <CODE>null</CODE> or not set
* the description "Signature Not Verified" will be used
*/
public void setLayer4Text(String text) {
layer4Text = text;
}
/**
* Gets the text identifying the signature status if set by setLayer4Text().
* @return the text identifying the signature status
*/
public String getLayer4Text() {
return layer4Text;
}
/**
* Gets the rectangle representing the signature dimensions.
* @return the rectangle representing the signature dimensions. It may be <CODE>null</CODE>
* or have zero width or height for invisible signatures
*/
public Rectangle getRect() {
return rect;
}
/**
* Gets the visibility status of the signature.
* @return the visibility status of the signature
*/
public boolean isInvisible() {
return (rect == null || rect.getWidth() == 0 || rect.getHeight() == 0);
}
/**
* Sets the cryptographic parameters.
* @param privKey the private key
* @param certChain the certificate chain
* @param crlList the certificate revocation list. It may be <CODE>null</CODE>
* @param filter the crytographic filter type. It can be SELF_SIGNED, VERISIGN_SIGNED or WINCER_SIGNED
*/
public void setCrypto(PrivateKey privKey, Certificate[] certChain, CRL[] crlList, PdfName filter) {
this.privKey = privKey;
this.certChain = certChain;
this.crlList = crlList;
this.filter = filter;
}
/**
* Sets the signature to be visible. It creates a new visible signature field.
* @param pageRect the position and dimension of the field in the page
* @param page the page to place the field. The fist page is 1
* @param fieldName the field name or <CODE>null</CODE> to generate automatically a new field name
*/
public void setVisibleSignature(Rectangle pageRect, int page, String fieldName) {
if (fieldName != null) {
if (fieldName.indexOf('.') >= 0)
throw new IllegalArgumentException("Field names cannot contain a dot.");
AcroFields af = writer.getAcroFields();
AcroFields.Item item = af.getFieldItem(fieldName);
if (item != null)
throw new IllegalArgumentException("The field " + fieldName + " already exists.");
this.fieldName = fieldName;
}
if (page < 1 || page > writer.reader.getNumberOfPages())
throw new IllegalArgumentException("Invalid page number: " + page);
this.pageRect = new Rectangle(pageRect);
this.pageRect.normalize();
rect = new Rectangle(this.pageRect.getWidth(), this.pageRect.getHeight());
this.page = page;
newField = true;
}
/**
* Sets the signature to be visible. An empty signature field with the same name must already exist.
* @param fieldName the existing empty signature field name
*/
public void setVisibleSignature(String fieldName) {
AcroFields af = writer.getAcroFields();
AcroFields.Item item = af.getFieldItem(fieldName);
if (item == null)
throw new IllegalArgumentException("The field " + fieldName + " does not exist.");
PdfDictionary merged = (PdfDictionary)item.merged.get(0);
if (!PdfName.SIG.equals(PdfReader.getPdfObject(merged.get(PdfName.FT))))
throw new IllegalArgumentException("The field " + fieldName + " is not a signature field.");
this.fieldName = fieldName;
PdfArray r = (PdfArray)PdfReader.getPdfObject(merged.get(PdfName.RECT));
ArrayList ar = r.getArrayList();
float llx = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(0))).floatValue();
float lly = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(1))).floatValue();
float urx = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(2))).floatValue();
float ury = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(3))).floatValue();
pageRect = new Rectangle(llx, lly, urx, ury);
pageRect.normalize();
page = ((Integer)item.page.get(0)).intValue();
int rotation = writer.reader.getPageRotation(page);
Rectangle pageSize = writer.reader.getPageSizeWithRotation(page);
switch (rotation) {
case 90:
pageRect = new Rectangle(
pageRect.getBottom(),
pageSize.getTop() - pageRect.getLeft(),
pageRect.getTop(),
pageSize.getTop() - pageRect.getRight());
break;
case 180:
pageRect = new Rectangle(
pageSize.getRight() - pageRect.getLeft(),
pageSize.getTop() - pageRect.getBottom(),
pageSize.getRight() - pageRect.getRight(),
pageSize.getTop() - pageRect.getTop());
break;
case 270:
pageRect = new Rectangle(
pageSize.getRight() - pageRect.getBottom(),
pageRect.getLeft(),
pageSize.getRight() - pageRect.getTop(),
pageRect.getRight());
break;
}
if (rotation != 0)
pageRect.normalize();
rect = new Rectangle(this.pageRect.getWidth(), this.pageRect.getHeight());
}
/**
* Gets a template layer to create a signature appearance. The layers can go from 0 to 4.
* <p>
* Consult <A HREF="http://partners.adobe.com/asn/developer/pdfs/tn/PPKAppearances.pdf">PPKAppearances.pdf</A>
* for further details.
* @param layer the layer
* @return a template
*/
public PdfTemplate getLayer(int layer) {
if (layer < 0 || layer >= app.length)
return null;
PdfTemplate t = app[layer];
if (t == null) {
t = app[layer] = new PdfTemplate(writer);
t.setBoundingBox(rect);
writer.addDirectTemplateSimple(t, new PdfName("n" + layer));
}
return t;
}
/**
* Gets the template that aggregates all appearance layers. This corresponds to the /FRM resource.
* <p>
* Consult <A HREF="http://partners.adobe.com/asn/developer/pdfs/tn/PPKAppearances.pdf">PPKAppearances.pdf</A>
* for further details.
* @return the template that aggregates all appearance layers
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -