📄 pdfsignatureappearance.java
字号:
return this.crlList;
}
/**
* Gets the filter used to sign the document.
* @return the filter used to sign the document
*/
public com.lowagie.text.pdf.PdfName getFilter() {
return filter;
}
/**
* Checks if a new field was created.
* @return <CODE>true</CODE> if a new field was created, <CODE>false</CODE> if signing
* an existing field or if the signature is invisible
*/
public boolean isNewField() {
return this.newField;
}
/**
* Gets the page number of the field.
* @return the page number of the field
*/
public int getPage() {
return page;
}
/**
* Gets the field name.
* @return the field name
*/
public java.lang.String getFieldName() {
return fieldName;
}
/**
* Gets the rectangle that represent the position and dimension of the signature in the page.
* @return the rectangle that represent the position and dimension of the signature in the page
*/
public com.lowagie.text.Rectangle getPageRect() {
return pageRect;
}
/**
* Gets the signature date.
* @return the signature date
*/
public java.util.Calendar getSignDate() {
return signDate;
}
/**
* Sets the signature date.
* @param signDate the signature date
*/
public void setSignDate(java.util.Calendar signDate) {
this.signDate = signDate;
}
com.lowagie.text.pdf.ByteBuffer getSigout() {
return sigout;
}
void setSigout(com.lowagie.text.pdf.ByteBuffer sigout) {
this.sigout = sigout;
}
java.io.OutputStream getOriginalout() {
return originalout;
}
void setOriginalout(java.io.OutputStream originalout) {
this.originalout = originalout;
}
/**
* Gets the temporary file.
* @return the temporary file or <CODE>null</CODE> is the document is created in memory
*/
public java.io.File getTempFile() {
return tempFile;
}
void setTempFile(java.io.File tempFile) {
this.tempFile = tempFile;
}
/**
* Gets a new signature fied name that doesn't clash with any existing name.
* @return a new signature fied name
*/
public String getNewSigName() {
AcroFields af = writer.getAcroFields();
String name = "Signature";
int step = 0;
boolean found = false;
while (!found) {
++step;
String n1 = name + step;
if (af.getFieldItem(n1) != null)
continue;
n1 += ".";
found = true;
for (Iterator it = af.getFields().keySet().iterator(); it.hasNext();) {
String fn = (String)it.next();
if (fn.startsWith(n1)) {
found = false;
break;
}
}
}
name += step;
return name;
}
/**
* This is the first method to be called when using external signatures. The general sequence is:
* preClose(), getDocumentBytes() and close().
* <p>
* If calling preClose() <B>dont't</B> call PdfStamper.close().
* <p>
* No external signatures are allowed if this methos is called.
* @throws IOException on error
* @throws DocumentException on error
*/
public void preClose() throws IOException, DocumentException {
preClose(null);
}
/**
* This is the first method to be called when using external signatures. The general sequence is:
* preClose(), getDocumentBytes() and close().
* <p>
* If calling preClose() <B>dont't</B> call PdfStamper.close().
* <p>
* If using an external signature <CODE>exclusionSizes</CODE> must contain at least
* the <CODE>PdfName.CONTENTS</CODE> key with the size that it will take in the
* document. Note that due to the hex string coding this size should be
* byte_size*2+2.
* @param exclusionSizes a <CODE>HashMap</CODE> with names and sizes to be excluded in the signature
* calculation. The key is a <CODE>PdfName</CODE> and the value an
* <CODE>Integer</CODE>. At least the <CODE>PdfName.CONTENTS</CODE> must be present
* @throws IOException on error
* @throws DocumentException on error
*/
public void preClose(HashMap exclusionSizes) throws IOException, DocumentException {
if (preClosed)
throw new DocumentException("Document already pre closed.");
preClosed = true;
AcroFields af = writer.getAcroFields();
String name = getFieldName();
boolean fieldExists = !(isInvisible() || isNewField());
int flags = PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_LOCKED;
PdfIndirectReference refSig = writer.getPdfIndirectReference();
writer.setSigFlags(3);
if (fieldExists) {
ArrayList widgets = af.getFieldItem(name).widgets;
PdfDictionary widget = (PdfDictionary)widgets.get(0);
writer.markUsed(widget);
widget.put(PdfName.P, writer.getPageReference(getPage()));
widget.put(PdfName.V, refSig);
PdfObject obj = PdfReader.getPdfObjectRelease(widget.get(PdfName.F));
if (obj != null && obj.isNumber())
flags = ((PdfNumber)obj).intValue() | PdfAnnotation.FLAGS_LOCKED;
widget.put(PdfName.F, new PdfNumber(flags));
PdfDictionary ap = new PdfDictionary();
ap.put(PdfName.N, getAppearance().getIndirectReference());
widget.put(PdfName.AP, ap);
}
else {
PdfFormField sigField = PdfFormField.createSignature(writer);
sigField.setFieldName(name);
sigField.put(PdfName.V, refSig);
sigField.setFlags(flags);
int pagen = getPage();
if (!isInvisible())
sigField.setWidget(getPageRect(), null);
else
sigField.setWidget(new Rectangle(0, 0), null);
sigField.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, getAppearance());
sigField.setPage(pagen);
writer.addAnnotation(sigField, pagen);
}
exclusionLocations = new HashMap();
if (cryptoDictionary == null) {
if (PdfName.ADOBE_PPKLITE.equals(getFilter()))
sigStandard = new PdfSigGenericPKCS.PPKLite(getProvider());
else if (PdfName.ADOBE_PPKMS.equals(getFilter()))
sigStandard = new PdfSigGenericPKCS.PPKMS(getProvider());
else if (PdfName.VERISIGN_PPKVS.equals(getFilter()))
sigStandard = new PdfSigGenericPKCS.VeriSign(getProvider());
else
throw new IllegalArgumentException("Unknown filter: " + getFilter());
sigStandard.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
if (getReason() != null)
sigStandard.setReason(getReason());
if (getLocation() != null)
sigStandard.setLocation(getLocation());
if (getContact() != null)
sigStandard.setContact(getContact());
sigStandard.put(PdfName.M, new PdfDate(getSignDate()));
sigStandard.setSignInfo(getPrivKey(), getCertChain(), getCrlList());
PdfString contents = (PdfString)sigStandard.get(PdfName.CONTENTS);
PdfLiteral lit = new PdfLiteral((contents.toString().length() + (PdfName.ADOBE_PPKLITE.equals(getFilter())?0:64)) * 2 + 2);
exclusionLocations.put(PdfName.CONTENTS, lit);
sigStandard.put(PdfName.CONTENTS, lit);
lit = new PdfLiteral(80);
exclusionLocations.put(PdfName.BYTERANGE, lit);
sigStandard.put(PdfName.BYTERANGE, lit);
if (certificationLevel > 0) {
addDocMDP(sigStandard);
}
if (signatureEvent != null)
signatureEvent.getSignatureDictionary(sigStandard);
writer.addToBody(sigStandard, refSig, false);
}
else {
PdfLiteral lit = new PdfLiteral(80);
exclusionLocations.put(PdfName.BYTERANGE, lit);
cryptoDictionary.put(PdfName.BYTERANGE, lit);
for (Iterator it = exclusionSizes.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry)it.next();
PdfName key = (PdfName)entry.getKey();
Integer v = (Integer)entry.getValue();
lit = new PdfLiteral(v.intValue());
exclusionLocations.put(key, lit);
cryptoDictionary.put(key, lit);
}
if (certificationLevel > 0)
addDocMDP(cryptoDictionary);
if (signatureEvent != null)
signatureEvent.getSignatureDictionary(cryptoDictionary);
writer.addToBody(cryptoDictionary, refSig, false);
}
if (certificationLevel > 0) {
// add DocMDP entry to root
PdfDictionary docmdp = new PdfDictionary();
docmdp.put(new PdfName("DocMDP"), refSig);
writer.reader.getCatalog().put(new PdfName("Perms"), docmdp);
}
writer.close(stamper.getMoreInfo());
range = new int[exclusionLocations.size() * 2];
int byteRangePosition = ((PdfLiteral)exclusionLocations.get(PdfName.BYTERANGE)).getPosition();
exclusionLocations.remove(PdfName.BYTERANGE);
int idx = 1;
for (Iterator it = exclusionLocations.values().iterator(); it.hasNext();) {
PdfLiteral lit = (PdfLiteral)it.next();
int n = lit.getPosition();
range[idx++] = n;
range[idx++] = lit.getPosLength() + n;
}
Arrays.sort(range, 1, range.length - 1);
for (int k = 3; k < range.length - 2; k += 2)
range[k] -= range[k - 1];
if (tempFile == null) {
bout = sigout.getBuffer();
boutLen = sigout.size();
range[range.length - 1] = boutLen - range[range.length - 2];
ByteBuffer bf = new ByteBuffer();
bf.append('[');
for (int k = 0; k < range.length; ++k)
bf.append(range[k]).append(' ');
bf.append(']');
System.arraycopy(bf.getBuffer(), 0, bout, byteRangePosition, bf.size());
}
else {
try {
raf = new RandomAccessFile(tempFile, "rw");
int boutLen = (int)raf.length();
range[range.length - 1] = boutLen - range[range.length - 2];
ByteBuffer bf = new ByteBuffer();
bf.append('[');
for (int k = 0; k < range.length; ++k)
bf.append(range[k]).append(' ');
bf.append(']');
raf.seek(byteRangePosition);
raf.write(bf.getBuffer(), 0, bf.size());
}
catch (IOException e) {
try{raf.close();}catch(Exception ee){}
try{tempFile.delete();}catch(Exception ee){}
throw e;
}
}
}
/**
* This is the last method to be called when using external signatures. The general sequence is:
* preClose(), getDocumentBytes() and close().
* <p>
* <CODE>update</CODE> is a <CODE>PdfDictionary</CODE> that must have exactly the
* same keys as the ones provided in {@link #preClose(HashMap)}.
* @param update a <CODE>PdfDictionary</CODE> with the key/value that will fill the holes defined
* in {@link #preClose(HashMap)}
* @throws DocumentException on error
* @throws IOException on error
*/
public void close(PdfDictionary update) throws IOException, DocumentException {
try {
if (!preClosed)
throw new DocumentException("preClose() must be called first.");
ByteBuffer bf = new ByteBuffer();
for (Iterator it = update.getKeys().iterator(); it.hasNext();) {
PdfName key = (PdfName)it.next();
PdfObject obj = update.get(key);
PdfLiteral lit = (PdfLiteral)exclusionLocations.get(key);
if (lit == null)
throw new IllegalArgumentException("The key " + key.toString() + " didn't reserve space in preClose().");
bf.reset();
obj.toPdf(null, bf);
if (bf.size() > lit.getPosLength())
throw new IllegalArgumentException("The key " + key.toString() + " is too big. Is " + bf.size() + ", reserved " + lit.getPosLength());
if (tempFile == null)
System.arraycopy(bf.getBuffer(), 0, bout, lit.getPosition(), bf.size());
else {
raf.seek(lit.getPosition());
raf.write(bf.getBuffer(), 0, bf.size());
}
}
if (update.size() != exclusionLocations.size())
throw new IllegalArgumentException("The update dictionary has less keys than required.");
if (tempFile == null) {
originalout.write(bout, 0, boutLen);
}
else {
if (originalout != null) {
raf.seek(0);
int length = (int)raf.length();
byte buf[] = new byte[8192];
while (length > 0) {
int r = raf.read(buf, 0, Math.min(buf.length, length));
if (r < 0)
throw new EOFException("Unexpected EOF");
originalout.write(buf, 0, r);
length -= r;
}
}
}
}
finally {
if (tempFile != null) {
try{raf.close();}catch(Exception ee){}
if (originalout != null)
try{tempFile.delete();}catch(Exception ee){}
}
if (originalout != null)
try{originalout.close();}catch(Exception e){}
}
}
private void addDocMDP(PdfDictionary crypto) {
PdfDictionary reference = new PdfDictionary();
PdfDictionary transformParams = new PdfDictionary();
transformParams.put(PdfName.P, new PdfNumber(certificationLevel));
transformParams.put(PdfName.V, new PdfName("1.2"));
transformParams.put(PdfName.TYPE, PdfName.TRANSFORMPARAMS);
reference.put(PdfName.TRANSFORMMETHOD, PdfName.DOCMDP);
reference.put(PdfName.TYPE, PdfName.SIGREF);
reference.put(PdfName.TRANSFORMPARAMS, transformParams);
reference.put(new PdfName("DigestValue"), new PdfString("aa"));
PdfArray loc = new PdfArray();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -